| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2009, 2010 Google Inc. All rights reserved. | 2 * Copyright (C) 2009, 2010 Google Inc. All rights reserved. |
| 3 * Copyright (C) 2009 Joseph Pecoraro | 3 * Copyright (C) 2009 Joseph Pecoraro |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions are | 6 * modification, are permitted provided that the following conditions are |
| 7 * met: | 7 * met: |
| 8 * | 8 * |
| 9 * * Redistributions of source code must retain the above copyright | 9 * * Redistributions of source code must retain the above copyright |
| 10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 30 */ | 30 */ |
| 31 | |
| 32 /** | 31 /** |
| 33 * @constructor | 32 * @unrestricted |
| 34 * @extends {WebInspector.SDKObject} | |
| 35 * @param {!WebInspector.DOMModel} domModel | |
| 36 */ | 33 */ |
| 37 WebInspector.DOMNode = function(domModel) | 34 WebInspector.DOMNode = class extends WebInspector.SDKObject { |
| 38 { | 35 /** |
| 39 WebInspector.SDKObject.call(this, domModel.target()); | 36 * @param {!WebInspector.DOMModel} domModel |
| 37 */ |
| 38 constructor(domModel) { |
| 39 super(domModel.target()); |
| 40 this._domModel = domModel; | 40 this._domModel = domModel; |
| 41 }; | 41 } |
| 42 | 42 |
| 43 /** | 43 /** |
| 44 * @param {!WebInspector.DOMModel} domModel | 44 * @param {!WebInspector.DOMModel} domModel |
| 45 * @param {?WebInspector.DOMDocument} doc | 45 * @param {?WebInspector.DOMDocument} doc |
| 46 * @param {boolean} isInShadowTree | 46 * @param {boolean} isInShadowTree |
| 47 * @param {!DOMAgent.Node} payload | 47 * @param {!DOMAgent.Node} payload |
| 48 * @return {!WebInspector.DOMNode} | 48 * @return {!WebInspector.DOMNode} |
| 49 */ | 49 */ |
| 50 WebInspector.DOMNode.create = function(domModel, doc, isInShadowTree, payload) | 50 static create(domModel, doc, isInShadowTree, payload) { |
| 51 { | |
| 52 var node = new WebInspector.DOMNode(domModel); | 51 var node = new WebInspector.DOMNode(domModel); |
| 53 node._init(doc, isInShadowTree, payload); | 52 node._init(doc, isInShadowTree, payload); |
| 54 return node; | 53 return node; |
| 55 } | 54 } |
| 55 |
| 56 /** |
| 57 * @param {?WebInspector.DOMDocument} doc |
| 58 * @param {boolean} isInShadowTree |
| 59 * @param {!DOMAgent.Node} payload |
| 60 */ |
| 61 _init(doc, isInShadowTree, payload) { |
| 62 this._agent = this._domModel._agent; |
| 63 this.ownerDocument = doc; |
| 64 this._isInShadowTree = isInShadowTree; |
| 65 |
| 66 this.id = payload.nodeId; |
| 67 this._domModel._idToDOMNode[this.id] = this; |
| 68 this._nodeType = payload.nodeType; |
| 69 this._nodeName = payload.nodeName; |
| 70 this._localName = payload.localName; |
| 71 this._nodeValue = payload.nodeValue; |
| 72 this._pseudoType = payload.pseudoType; |
| 73 this._shadowRootType = payload.shadowRootType; |
| 74 this._frameOwnerFrameId = payload.frameId || null; |
| 75 this._xmlVersion = payload.xmlVersion; |
| 76 |
| 77 this._shadowRoots = []; |
| 78 |
| 79 this._attributes = []; |
| 80 this._attributesMap = {}; |
| 81 if (payload.attributes) |
| 82 this._setAttributesPayload(payload.attributes); |
| 83 |
| 84 /** @type {!Map<string, ?>} */ |
| 85 this._markers = new Map(); |
| 86 this._subtreeMarkerCount = 0; |
| 87 |
| 88 this._childNodeCount = payload.childNodeCount || 0; |
| 89 this._children = null; |
| 90 |
| 91 this.nextSibling = null; |
| 92 this.previousSibling = null; |
| 93 this.firstChild = null; |
| 94 this.lastChild = null; |
| 95 this.parentNode = null; |
| 96 |
| 97 if (payload.shadowRoots) { |
| 98 for (var i = 0; i < payload.shadowRoots.length; ++i) { |
| 99 var root = payload.shadowRoots[i]; |
| 100 var node = WebInspector.DOMNode.create(this._domModel, this.ownerDocumen
t, true, root); |
| 101 this._shadowRoots.push(node); |
| 102 node.parentNode = this; |
| 103 } |
| 104 } |
| 105 |
| 106 if (payload.templateContent) { |
| 107 this._templateContent = |
| 108 WebInspector.DOMNode.create(this._domModel, this.ownerDocument, true,
payload.templateContent); |
| 109 this._templateContent.parentNode = this; |
| 110 } |
| 111 |
| 112 if (payload.importedDocument) { |
| 113 this._importedDocument = |
| 114 WebInspector.DOMNode.create(this._domModel, this.ownerDocument, true,
payload.importedDocument); |
| 115 this._importedDocument.parentNode = this; |
| 116 } |
| 117 |
| 118 if (payload.distributedNodes) |
| 119 this._setDistributedNodePayloads(payload.distributedNodes); |
| 120 |
| 121 if (payload.children) |
| 122 this._setChildrenPayload(payload.children); |
| 123 |
| 124 this._setPseudoElements(payload.pseudoElements); |
| 125 |
| 126 if (payload.contentDocument) { |
| 127 this._contentDocument = new WebInspector.DOMDocument(this._domModel, paylo
ad.contentDocument); |
| 128 this._children = [this._contentDocument]; |
| 129 this._renumber(); |
| 130 } |
| 131 |
| 132 if (this._nodeType === Node.ELEMENT_NODE) { |
| 133 // HTML and BODY from internal iframes should not overwrite top-level ones
. |
| 134 if (this.ownerDocument && !this.ownerDocument.documentElement && this._nod
eName === 'HTML') |
| 135 this.ownerDocument.documentElement = this; |
| 136 if (this.ownerDocument && !this.ownerDocument.body && this._nodeName === '
BODY') |
| 137 this.ownerDocument.body = this; |
| 138 } else if (this._nodeType === Node.DOCUMENT_TYPE_NODE) { |
| 139 this.publicId = payload.publicId; |
| 140 this.systemId = payload.systemId; |
| 141 this.internalSubset = payload.internalSubset; |
| 142 } else if (this._nodeType === Node.ATTRIBUTE_NODE) { |
| 143 this.name = payload.name; |
| 144 this.value = payload.value; |
| 145 } |
| 146 } |
| 147 |
| 148 /** |
| 149 * @return {!WebInspector.DOMModel} |
| 150 */ |
| 151 domModel() { |
| 152 return this._domModel; |
| 153 } |
| 154 |
| 155 /** |
| 156 * @return {?Array.<!WebInspector.DOMNode>} |
| 157 */ |
| 158 children() { |
| 159 return this._children ? this._children.slice() : null; |
| 160 } |
| 161 |
| 162 /** |
| 163 * @return {boolean} |
| 164 */ |
| 165 hasAttributes() { |
| 166 return this._attributes.length > 0; |
| 167 } |
| 168 |
| 169 /** |
| 170 * @return {number} |
| 171 */ |
| 172 childNodeCount() { |
| 173 return this._childNodeCount; |
| 174 } |
| 175 |
| 176 /** |
| 177 * @return {boolean} |
| 178 */ |
| 179 hasShadowRoots() { |
| 180 return !!this._shadowRoots.length; |
| 181 } |
| 182 |
| 183 /** |
| 184 * @return {!Array.<!WebInspector.DOMNode>} |
| 185 */ |
| 186 shadowRoots() { |
| 187 return this._shadowRoots.slice(); |
| 188 } |
| 189 |
| 190 /** |
| 191 * @return {?WebInspector.DOMNode} |
| 192 */ |
| 193 templateContent() { |
| 194 return this._templateContent || null; |
| 195 } |
| 196 |
| 197 /** |
| 198 * @return {?WebInspector.DOMNode} |
| 199 */ |
| 200 importedDocument() { |
| 201 return this._importedDocument || null; |
| 202 } |
| 203 |
| 204 /** |
| 205 * @return {number} |
| 206 */ |
| 207 nodeType() { |
| 208 return this._nodeType; |
| 209 } |
| 210 |
| 211 /** |
| 212 * @return {string} |
| 213 */ |
| 214 nodeName() { |
| 215 return this._nodeName; |
| 216 } |
| 217 |
| 218 /** |
| 219 * @return {string|undefined} |
| 220 */ |
| 221 pseudoType() { |
| 222 return this._pseudoType; |
| 223 } |
| 224 |
| 225 /** |
| 226 * @return {boolean} |
| 227 */ |
| 228 hasPseudoElements() { |
| 229 return this._pseudoElements.size > 0; |
| 230 } |
| 231 |
| 232 /** |
| 233 * @return {!Map<string, !WebInspector.DOMNode>} |
| 234 */ |
| 235 pseudoElements() { |
| 236 return this._pseudoElements; |
| 237 } |
| 238 |
| 239 /** |
| 240 * @return {?WebInspector.DOMNode} |
| 241 */ |
| 242 beforePseudoElement() { |
| 243 if (!this._pseudoElements) |
| 244 return null; |
| 245 return this._pseudoElements.get(WebInspector.DOMNode.PseudoElementNames.Befo
re); |
| 246 } |
| 247 |
| 248 /** |
| 249 * @return {?WebInspector.DOMNode} |
| 250 */ |
| 251 afterPseudoElement() { |
| 252 if (!this._pseudoElements) |
| 253 return null; |
| 254 return this._pseudoElements.get(WebInspector.DOMNode.PseudoElementNames.Afte
r); |
| 255 } |
| 256 |
| 257 /** |
| 258 * @return {boolean} |
| 259 */ |
| 260 isInsertionPoint() { |
| 261 return !this.isXMLNode() && |
| 262 (this._nodeName === 'SHADOW' || this._nodeName === 'CONTENT' || this._no
deName === 'SLOT'); |
| 263 } |
| 264 |
| 265 /** |
| 266 * @return {!Array.<!WebInspector.DOMNodeShortcut>} |
| 267 */ |
| 268 distributedNodes() { |
| 269 return this._distributedNodes || []; |
| 270 } |
| 271 |
| 272 /** |
| 273 * @return {boolean} |
| 274 */ |
| 275 isInShadowTree() { |
| 276 return this._isInShadowTree; |
| 277 } |
| 278 |
| 279 /** |
| 280 * @return {?WebInspector.DOMNode} |
| 281 */ |
| 282 ancestorShadowHost() { |
| 283 var ancestorShadowRoot = this.ancestorShadowRoot(); |
| 284 return ancestorShadowRoot ? ancestorShadowRoot.parentNode : null; |
| 285 } |
| 286 |
| 287 /** |
| 288 * @return {?WebInspector.DOMNode} |
| 289 */ |
| 290 ancestorShadowRoot() { |
| 291 if (!this._isInShadowTree) |
| 292 return null; |
| 293 |
| 294 var current = this; |
| 295 while (current && !current.isShadowRoot()) |
| 296 current = current.parentNode; |
| 297 return current; |
| 298 } |
| 299 |
| 300 /** |
| 301 * @return {?WebInspector.DOMNode} |
| 302 */ |
| 303 ancestorUserAgentShadowRoot() { |
| 304 var ancestorShadowRoot = this.ancestorShadowRoot(); |
| 305 if (!ancestorShadowRoot) |
| 306 return null; |
| 307 return ancestorShadowRoot.shadowRootType() === WebInspector.DOMNode.ShadowRo
otTypes.UserAgent ? ancestorShadowRoot : |
| 308
null; |
| 309 } |
| 310 |
| 311 /** |
| 312 * @return {boolean} |
| 313 */ |
| 314 isShadowRoot() { |
| 315 return !!this._shadowRootType; |
| 316 } |
| 317 |
| 318 /** |
| 319 * @return {?string} |
| 320 */ |
| 321 shadowRootType() { |
| 322 return this._shadowRootType || null; |
| 323 } |
| 324 |
| 325 /** |
| 326 * @return {string} |
| 327 */ |
| 328 nodeNameInCorrectCase() { |
| 329 var shadowRootType = this.shadowRootType(); |
| 330 if (shadowRootType) |
| 331 return '#shadow-root (' + shadowRootType + ')'; |
| 332 |
| 333 // If there is no local name, it's case sensitive |
| 334 if (!this.localName()) |
| 335 return this.nodeName(); |
| 336 |
| 337 // If the names are different lengths, there is a prefix and it's case sensi
tive |
| 338 if (this.localName().length !== this.nodeName().length) |
| 339 return this.nodeName(); |
| 340 |
| 341 // Return the localname, which will be case insensitive if its an html node |
| 342 return this.localName(); |
| 343 } |
| 344 |
| 345 /** |
| 346 * @param {string} name |
| 347 * @param {function(?Protocol.Error, number)=} callback |
| 348 */ |
| 349 setNodeName(name, callback) { |
| 350 this._agent.setNodeName(this.id, name, this._domModel._markRevision(this, ca
llback)); |
| 351 } |
| 352 |
| 353 /** |
| 354 * @return {string} |
| 355 */ |
| 356 localName() { |
| 357 return this._localName; |
| 358 } |
| 359 |
| 360 /** |
| 361 * @return {string} |
| 362 */ |
| 363 nodeValue() { |
| 364 return this._nodeValue; |
| 365 } |
| 366 |
| 367 /** |
| 368 * @param {string} value |
| 369 * @param {function(?Protocol.Error)=} callback |
| 370 */ |
| 371 setNodeValue(value, callback) { |
| 372 this._agent.setNodeValue(this.id, value, this._domModel._markRevision(this,
callback)); |
| 373 } |
| 374 |
| 375 /** |
| 376 * @param {string} name |
| 377 * @return {string} |
| 378 */ |
| 379 getAttribute(name) { |
| 380 var attr = this._attributesMap[name]; |
| 381 return attr ? attr.value : undefined; |
| 382 } |
| 383 |
| 384 /** |
| 385 * @param {string} name |
| 386 * @param {string} text |
| 387 * @param {function(?Protocol.Error)=} callback |
| 388 */ |
| 389 setAttribute(name, text, callback) { |
| 390 this._agent.setAttributesAsText(this.id, text, name, this._domModel._markRev
ision(this, callback)); |
| 391 } |
| 392 |
| 393 /** |
| 394 * @param {string} name |
| 395 * @param {string} value |
| 396 * @param {function(?Protocol.Error)=} callback |
| 397 */ |
| 398 setAttributeValue(name, value, callback) { |
| 399 this._agent.setAttributeValue(this.id, name, value, this._domModel._markRevi
sion(this, callback)); |
| 400 } |
| 401 |
| 402 /** |
| 403 * @return {!Array<!WebInspector.DOMNode.Attribute>} |
| 404 */ |
| 405 attributes() { |
| 406 return this._attributes; |
| 407 } |
| 408 |
| 409 /** |
| 410 * @param {string} name |
| 411 * @param {function(?Protocol.Error)=} callback |
| 412 */ |
| 413 removeAttribute(name, callback) { |
| 414 /** |
| 415 * @param {?Protocol.Error} error |
| 416 * @this {WebInspector.DOMNode} |
| 417 */ |
| 418 function mycallback(error) { |
| 419 if (!error) { |
| 420 delete this._attributesMap[name]; |
| 421 for (var i = 0; i < this._attributes.length; ++i) { |
| 422 if (this._attributes[i].name === name) { |
| 423 this._attributes.splice(i, 1); |
| 424 break; |
| 425 } |
| 426 } |
| 427 } |
| 428 |
| 429 this._domModel._markRevision(this, callback)(error); |
| 430 } |
| 431 this._agent.removeAttribute(this.id, name, mycallback.bind(this)); |
| 432 } |
| 433 |
| 434 /** |
| 435 * @param {function(?Array.<!WebInspector.DOMNode>)=} callback |
| 436 */ |
| 437 getChildNodes(callback) { |
| 438 if (this._children) { |
| 439 if (callback) |
| 440 callback(this.children()); |
| 441 return; |
| 442 } |
| 443 |
| 444 /** |
| 445 * @this {WebInspector.DOMNode} |
| 446 * @param {?Protocol.Error} error |
| 447 */ |
| 448 function mycallback(error) { |
| 449 if (callback) |
| 450 callback(error ? null : this.children()); |
| 451 } |
| 452 |
| 453 this._agent.requestChildNodes(this.id, undefined, mycallback.bind(this)); |
| 454 } |
| 455 |
| 456 /** |
| 457 * @param {number} depth |
| 458 * @param {function(?Array.<!WebInspector.DOMNode>)=} callback |
| 459 */ |
| 460 getSubtree(depth, callback) { |
| 461 /** |
| 462 * @this {WebInspector.DOMNode} |
| 463 * @param {?Protocol.Error} error |
| 464 */ |
| 465 function mycallback(error) { |
| 466 if (callback) |
| 467 callback(error ? null : this._children); |
| 468 } |
| 469 |
| 470 this._agent.requestChildNodes(this.id, depth, mycallback.bind(this)); |
| 471 } |
| 472 |
| 473 /** |
| 474 * @param {function(?Protocol.Error, string)=} callback |
| 475 */ |
| 476 getOuterHTML(callback) { |
| 477 this._agent.getOuterHTML(this.id, callback); |
| 478 } |
| 479 |
| 480 /** |
| 481 * @param {string} html |
| 482 * @param {function(?Protocol.Error)=} callback |
| 483 */ |
| 484 setOuterHTML(html, callback) { |
| 485 this._agent.setOuterHTML(this.id, html, this._domModel._markRevision(this, c
allback)); |
| 486 } |
| 487 |
| 488 /** |
| 489 * @param {function(?Protocol.Error, !DOMAgent.NodeId=)=} callback |
| 490 */ |
| 491 removeNode(callback) { |
| 492 this._agent.removeNode(this.id, this._domModel._markRevision(this, callback)
); |
| 493 } |
| 494 |
| 495 /** |
| 496 * @param {function(?string)=} callback |
| 497 */ |
| 498 copyNode(callback) { |
| 499 function copy(error, text) { |
| 500 if (!error) |
| 501 InspectorFrontendHost.copyText(text); |
| 502 if (callback) |
| 503 callback(error ? null : text); |
| 504 } |
| 505 this._agent.getOuterHTML(this.id, copy); |
| 506 } |
| 507 |
| 508 /** |
| 509 * @return {string} |
| 510 */ |
| 511 path() { |
| 512 /** |
| 513 * @param {?WebInspector.DOMNode} node |
| 514 */ |
| 515 function canPush(node) { |
| 516 return node && ('index' in node || (node.isShadowRoot() && node.parentNode
)) && node._nodeName.length; |
| 517 } |
| 518 |
| 519 var path = []; |
| 520 var node = this; |
| 521 while (canPush(node)) { |
| 522 var index = typeof node.index === 'number' ? |
| 523 node.index : |
| 524 (node.shadowRootType() === WebInspector.DOMNode.ShadowRootTypes.UserAg
ent ? 'u' : 'a'); |
| 525 path.push([index, node._nodeName]); |
| 526 node = node.parentNode; |
| 527 } |
| 528 path.reverse(); |
| 529 return path.join(','); |
| 530 } |
| 531 |
| 532 /** |
| 533 * @param {!WebInspector.DOMNode} node |
| 534 * @return {boolean} |
| 535 */ |
| 536 isAncestor(node) { |
| 537 if (!node) |
| 538 return false; |
| 539 |
| 540 var currentNode = node.parentNode; |
| 541 while (currentNode) { |
| 542 if (this === currentNode) |
| 543 return true; |
| 544 currentNode = currentNode.parentNode; |
| 545 } |
| 546 return false; |
| 547 } |
| 548 |
| 549 /** |
| 550 * @param {!WebInspector.DOMNode} descendant |
| 551 * @return {boolean} |
| 552 */ |
| 553 isDescendant(descendant) { |
| 554 return descendant !== null && descendant.isAncestor(this); |
| 555 } |
| 556 |
| 557 /** |
| 558 * @return {?PageAgent.FrameId} |
| 559 */ |
| 560 frameId() { |
| 561 var node = this.parentNode || this; |
| 562 while (!node._frameOwnerFrameId && node.parentNode) |
| 563 node = node.parentNode; |
| 564 return node._frameOwnerFrameId; |
| 565 } |
| 566 |
| 567 /** |
| 568 * @param {!Array.<string>} attrs |
| 569 * @return {boolean} |
| 570 */ |
| 571 _setAttributesPayload(attrs) { |
| 572 var attributesChanged = !this._attributes || attrs.length !== this._attribut
es.length * 2; |
| 573 var oldAttributesMap = this._attributesMap || {}; |
| 574 |
| 575 this._attributes = []; |
| 576 this._attributesMap = {}; |
| 577 |
| 578 for (var i = 0; i < attrs.length; i += 2) { |
| 579 var name = attrs[i]; |
| 580 var value = attrs[i + 1]; |
| 581 this._addAttribute(name, value); |
| 582 |
| 583 if (attributesChanged) |
| 584 continue; |
| 585 |
| 586 if (!oldAttributesMap[name] || oldAttributesMap[name].value !== value) |
| 587 attributesChanged = true; |
| 588 } |
| 589 return attributesChanged; |
| 590 } |
| 591 |
| 592 /** |
| 593 * @param {!WebInspector.DOMNode} prev |
| 594 * @param {!DOMAgent.Node} payload |
| 595 * @return {!WebInspector.DOMNode} |
| 596 */ |
| 597 _insertChild(prev, payload) { |
| 598 var node = WebInspector.DOMNode.create(this._domModel, this.ownerDocument, t
his._isInShadowTree, payload); |
| 599 this._children.splice(this._children.indexOf(prev) + 1, 0, node); |
| 600 this._renumber(); |
| 601 return node; |
| 602 } |
| 603 |
| 604 /** |
| 605 * @param {!WebInspector.DOMNode} node |
| 606 */ |
| 607 _removeChild(node) { |
| 608 if (node.pseudoType()) { |
| 609 this._pseudoElements.delete(node.pseudoType()); |
| 610 } else { |
| 611 var shadowRootIndex = this._shadowRoots.indexOf(node); |
| 612 if (shadowRootIndex !== -1) { |
| 613 this._shadowRoots.splice(shadowRootIndex, 1); |
| 614 } else { |
| 615 console.assert(this._children.indexOf(node) !== -1); |
| 616 this._children.splice(this._children.indexOf(node), 1); |
| 617 } |
| 618 } |
| 619 node.parentNode = null; |
| 620 this._subtreeMarkerCount -= node._subtreeMarkerCount; |
| 621 if (node._subtreeMarkerCount) |
| 622 this._domModel.dispatchEventToListeners(WebInspector.DOMModel.Events.Marke
rsChanged, this); |
| 623 this._renumber(); |
| 624 } |
| 625 |
| 626 /** |
| 627 * @param {!Array.<!DOMAgent.Node>} payloads |
| 628 */ |
| 629 _setChildrenPayload(payloads) { |
| 630 // We set children in the constructor. |
| 631 if (this._contentDocument) |
| 632 return; |
| 633 |
| 634 this._children = []; |
| 635 for (var i = 0; i < payloads.length; ++i) { |
| 636 var payload = payloads[i]; |
| 637 var node = WebInspector.DOMNode.create(this._domModel, this.ownerDocument,
this._isInShadowTree, payload); |
| 638 this._children.push(node); |
| 639 } |
| 640 this._renumber(); |
| 641 } |
| 642 |
| 643 /** |
| 644 * @param {!Array.<!DOMAgent.Node>|undefined} payloads |
| 645 */ |
| 646 _setPseudoElements(payloads) { |
| 647 this._pseudoElements = new Map(); |
| 648 if (!payloads) |
| 649 return; |
| 650 |
| 651 for (var i = 0; i < payloads.length; ++i) { |
| 652 var node = WebInspector.DOMNode.create(this._domModel, this.ownerDocument,
this._isInShadowTree, payloads[i]); |
| 653 node.parentNode = this; |
| 654 this._pseudoElements.set(node.pseudoType(), node); |
| 655 } |
| 656 } |
| 657 |
| 658 /** |
| 659 * @param {!Array.<!DOMAgent.BackendNode>} payloads |
| 660 */ |
| 661 _setDistributedNodePayloads(payloads) { |
| 662 this._distributedNodes = []; |
| 663 for (var payload of payloads) |
| 664 this._distributedNodes.push(new WebInspector.DOMNodeShortcut( |
| 665 this._domModel.target(), payload.backendNodeId, payload.nodeType, payl
oad.nodeName)); |
| 666 } |
| 667 |
| 668 _renumber() { |
| 669 this._childNodeCount = this._children.length; |
| 670 if (this._childNodeCount === 0) { |
| 671 this.firstChild = null; |
| 672 this.lastChild = null; |
| 673 return; |
| 674 } |
| 675 this.firstChild = this._children[0]; |
| 676 this.lastChild = this._children[this._childNodeCount - 1]; |
| 677 for (var i = 0; i < this._childNodeCount; ++i) { |
| 678 var child = this._children[i]; |
| 679 child.index = i; |
| 680 child.nextSibling = i + 1 < this._childNodeCount ? this._children[i + 1] :
null; |
| 681 child.previousSibling = i - 1 >= 0 ? this._children[i - 1] : null; |
| 682 child.parentNode = this; |
| 683 } |
| 684 } |
| 685 |
| 686 /** |
| 687 * @param {string} name |
| 688 * @param {string} value |
| 689 */ |
| 690 _addAttribute(name, value) { |
| 691 var attr = {name: name, value: value, _node: this}; |
| 692 this._attributesMap[name] = attr; |
| 693 this._attributes.push(attr); |
| 694 } |
| 695 |
| 696 /** |
| 697 * @param {string} name |
| 698 * @param {string} value |
| 699 */ |
| 700 _setAttribute(name, value) { |
| 701 var attr = this._attributesMap[name]; |
| 702 if (attr) |
| 703 attr.value = value; |
| 704 else |
| 705 this._addAttribute(name, value); |
| 706 } |
| 707 |
| 708 /** |
| 709 * @param {string} name |
| 710 */ |
| 711 _removeAttribute(name) { |
| 712 var attr = this._attributesMap[name]; |
| 713 if (attr) { |
| 714 this._attributes.remove(attr); |
| 715 delete this._attributesMap[name]; |
| 716 } |
| 717 } |
| 718 |
| 719 /** |
| 720 * @param {!WebInspector.DOMNode} targetNode |
| 721 * @param {?WebInspector.DOMNode} anchorNode |
| 722 * @param {function(?Protocol.Error, !DOMAgent.NodeId=)=} callback |
| 723 */ |
| 724 copyTo(targetNode, anchorNode, callback) { |
| 725 this._agent.copyTo( |
| 726 this.id, targetNode.id, anchorNode ? anchorNode.id : undefined, this._do
mModel._markRevision(this, callback)); |
| 727 } |
| 728 |
| 729 /** |
| 730 * @param {!WebInspector.DOMNode} targetNode |
| 731 * @param {?WebInspector.DOMNode} anchorNode |
| 732 * @param {function(?Protocol.Error, !DOMAgent.NodeId=)=} callback |
| 733 */ |
| 734 moveTo(targetNode, anchorNode, callback) { |
| 735 this._agent.moveTo( |
| 736 this.id, targetNode.id, anchorNode ? anchorNode.id : undefined, this._do
mModel._markRevision(this, callback)); |
| 737 } |
| 738 |
| 739 /** |
| 740 * @return {boolean} |
| 741 */ |
| 742 isXMLNode() { |
| 743 return !!this._xmlVersion; |
| 744 } |
| 745 |
| 746 /** |
| 747 * @param {string} name |
| 748 * @param {?*} value |
| 749 */ |
| 750 setMarker(name, value) { |
| 751 if (value === null) { |
| 752 if (!this._markers.has(name)) |
| 753 return; |
| 754 |
| 755 this._markers.delete(name); |
| 756 for (var node = this; node; node = node.parentNode) |
| 757 --node._subtreeMarkerCount; |
| 758 for (var node = this; node; node = node.parentNode) |
| 759 this._domModel.dispatchEventToListeners(WebInspector.DOMModel.Events.Mar
kersChanged, node); |
| 760 return; |
| 761 } |
| 762 |
| 763 if (this.parentNode && !this._markers.has(name)) { |
| 764 for (var node = this; node; node = node.parentNode) |
| 765 ++node._subtreeMarkerCount; |
| 766 } |
| 767 this._markers.set(name, value); |
| 768 for (var node = this; node; node = node.parentNode) |
| 769 this._domModel.dispatchEventToListeners(WebInspector.DOMModel.Events.Marke
rsChanged, node); |
| 770 } |
| 771 |
| 772 /** |
| 773 * @param {string} name |
| 774 * @return {?T} |
| 775 * @template T |
| 776 */ |
| 777 marker(name) { |
| 778 return this._markers.get(name) || null; |
| 779 } |
| 780 |
| 781 /** |
| 782 * @param {function(!WebInspector.DOMNode, string)} visitor |
| 783 */ |
| 784 traverseMarkers(visitor) { |
| 785 /** |
| 786 * @param {!WebInspector.DOMNode} node |
| 787 */ |
| 788 function traverse(node) { |
| 789 if (!node._subtreeMarkerCount) |
| 790 return; |
| 791 for (var marker of node._markers.keys()) |
| 792 visitor(node, marker); |
| 793 if (!node._children) |
| 794 return; |
| 795 for (var child of node._children) |
| 796 traverse(child); |
| 797 } |
| 798 traverse(this); |
| 799 } |
| 800 |
| 801 /** |
| 802 * @param {string} url |
| 803 * @return {?string} |
| 804 */ |
| 805 resolveURL(url) { |
| 806 if (!url) |
| 807 return url; |
| 808 for (var frameOwnerCandidate = this; frameOwnerCandidate; frameOwnerCandidat
e = frameOwnerCandidate.parentNode) { |
| 809 if (frameOwnerCandidate.baseURL) |
| 810 return WebInspector.ParsedURL.completeURL(frameOwnerCandidate.baseURL, u
rl); |
| 811 } |
| 812 return null; |
| 813 } |
| 814 |
| 815 /** |
| 816 * @param {string=} mode |
| 817 * @param {!RuntimeAgent.RemoteObjectId=} objectId |
| 818 */ |
| 819 highlight(mode, objectId) { |
| 820 this._domModel.highlightDOMNode(this.id, mode, undefined, objectId); |
| 821 } |
| 822 |
| 823 highlightForTwoSeconds() { |
| 824 this._domModel.highlightDOMNodeForTwoSeconds(this.id); |
| 825 } |
| 826 |
| 827 /** |
| 828 * @param {string=} objectGroup |
| 829 * @param {function(?WebInspector.RemoteObject)=} callback |
| 830 */ |
| 831 resolveToObject(objectGroup, callback) { |
| 832 this._agent.resolveNode(this.id, objectGroup, mycallback.bind(this)); |
| 833 |
| 834 /** |
| 835 * @param {?Protocol.Error} error |
| 836 * @param {!RuntimeAgent.RemoteObject} object |
| 837 * @this {WebInspector.DOMNode} |
| 838 */ |
| 839 function mycallback(error, object) { |
| 840 if (!callback) |
| 841 return; |
| 842 |
| 843 if (error || !object) |
| 844 callback(null); |
| 845 else |
| 846 callback(this.target().runtimeModel.createRemoteObject(object)); |
| 847 } |
| 848 } |
| 849 |
| 850 /** |
| 851 * @param {string=} objectGroup |
| 852 * @return {!Promise<!WebInspector.RemoteObject>} |
| 853 */ |
| 854 resolveToObjectPromise(objectGroup) { |
| 855 return new Promise(resolveToObject.bind(this)); |
| 856 /** |
| 857 * @param {function(?)} fulfill |
| 858 * @param {function(*)} reject |
| 859 * @this {WebInspector.DOMNode} |
| 860 */ |
| 861 function resolveToObject(fulfill, reject) { |
| 862 this.resolveToObject(objectGroup, mycallback); |
| 863 function mycallback(object) { |
| 864 if (object) |
| 865 fulfill(object); |
| 866 else |
| 867 reject(null); |
| 868 } |
| 869 } |
| 870 } |
| 871 |
| 872 /** |
| 873 * @param {function(?DOMAgent.BoxModel)} callback |
| 874 */ |
| 875 boxModel(callback) { |
| 876 this._agent.getBoxModel(this.id, this._domModel._wrapClientCallback(callback
)); |
| 877 } |
| 878 |
| 879 setAsInspectedNode() { |
| 880 var node = this; |
| 881 while (true) { |
| 882 var ancestor = node.ancestorUserAgentShadowRoot(); |
| 883 if (!ancestor) |
| 884 break; |
| 885 ancestor = node.ancestorShadowHost(); |
| 886 if (!ancestor) |
| 887 break; |
| 888 // User agent shadow root, keep climbing up. |
| 889 node = ancestor; |
| 890 } |
| 891 this._agent.setInspectedNode(node.id); |
| 892 } |
| 893 |
| 894 /** |
| 895 * @return {?WebInspector.DOMNode} |
| 896 */ |
| 897 enclosingElementOrSelf() { |
| 898 var node = this; |
| 899 if (node && node.nodeType() === Node.TEXT_NODE && node.parentNode) |
| 900 node = node.parentNode; |
| 901 |
| 902 if (node && node.nodeType() !== Node.ELEMENT_NODE) |
| 903 node = null; |
| 904 return node; |
| 905 } |
| 906 }; |
| 56 | 907 |
| 57 /** | 908 /** |
| 58 * @enum {string} | 909 * @enum {string} |
| 59 */ | 910 */ |
| 60 WebInspector.DOMNode.PseudoElementNames = { | 911 WebInspector.DOMNode.PseudoElementNames = { |
| 61 Before: "before", | 912 Before: 'before', |
| 62 After: "after" | 913 After: 'after' |
| 63 }; | 914 }; |
| 64 | 915 |
| 65 /** | 916 /** |
| 66 * @enum {string} | 917 * @enum {string} |
| 67 */ | 918 */ |
| 68 WebInspector.DOMNode.ShadowRootTypes = { | 919 WebInspector.DOMNode.ShadowRootTypes = { |
| 69 UserAgent: "user-agent", | 920 UserAgent: 'user-agent', |
| 70 Open: "open", | 921 Open: 'open', |
| 71 Closed: "closed" | 922 Closed: 'closed' |
| 72 }; | 923 }; |
| 73 | 924 |
| 74 /** @typedef {{name: string, value: string, _node: WebInspector.DOMNode}} */ | 925 /** @typedef {{name: string, value: string, _node: WebInspector.DOMNode}} */ |
| 75 WebInspector.DOMNode.Attribute; | 926 WebInspector.DOMNode.Attribute; |
| 76 | 927 |
| 77 WebInspector.DOMNode.prototype = { | |
| 78 /** | |
| 79 * @param {?WebInspector.DOMDocument} doc | |
| 80 * @param {boolean} isInShadowTree | |
| 81 * @param {!DOMAgent.Node} payload | |
| 82 */ | |
| 83 _init: function(doc, isInShadowTree, payload) | |
| 84 { | |
| 85 this._agent = this._domModel._agent; | |
| 86 this.ownerDocument = doc; | |
| 87 this._isInShadowTree = isInShadowTree; | |
| 88 | |
| 89 this.id = payload.nodeId; | |
| 90 this._domModel._idToDOMNode[this.id] = this; | |
| 91 this._nodeType = payload.nodeType; | |
| 92 this._nodeName = payload.nodeName; | |
| 93 this._localName = payload.localName; | |
| 94 this._nodeValue = payload.nodeValue; | |
| 95 this._pseudoType = payload.pseudoType; | |
| 96 this._shadowRootType = payload.shadowRootType; | |
| 97 this._frameOwnerFrameId = payload.frameId || null; | |
| 98 this._xmlVersion = payload.xmlVersion; | |
| 99 | |
| 100 this._shadowRoots = []; | |
| 101 | |
| 102 this._attributes = []; | |
| 103 this._attributesMap = {}; | |
| 104 if (payload.attributes) | |
| 105 this._setAttributesPayload(payload.attributes); | |
| 106 | |
| 107 /** @type {!Map<string, ?>} */ | |
| 108 this._markers = new Map(); | |
| 109 this._subtreeMarkerCount = 0; | |
| 110 | |
| 111 this._childNodeCount = payload.childNodeCount || 0; | |
| 112 this._children = null; | |
| 113 | |
| 114 this.nextSibling = null; | |
| 115 this.previousSibling = null; | |
| 116 this.firstChild = null; | |
| 117 this.lastChild = null; | |
| 118 this.parentNode = null; | |
| 119 | |
| 120 if (payload.shadowRoots) { | |
| 121 for (var i = 0; i < payload.shadowRoots.length; ++i) { | |
| 122 var root = payload.shadowRoots[i]; | |
| 123 var node = WebInspector.DOMNode.create(this._domModel, this.owne
rDocument, true, root); | |
| 124 this._shadowRoots.push(node); | |
| 125 node.parentNode = this; | |
| 126 } | |
| 127 } | |
| 128 | |
| 129 if (payload.templateContent) { | |
| 130 this._templateContent = WebInspector.DOMNode.create(this._domModel,
this.ownerDocument, true, payload.templateContent); | |
| 131 this._templateContent.parentNode = this; | |
| 132 } | |
| 133 | |
| 134 if (payload.importedDocument) { | |
| 135 this._importedDocument = WebInspector.DOMNode.create(this._domModel,
this.ownerDocument, true, payload.importedDocument); | |
| 136 this._importedDocument.parentNode = this; | |
| 137 } | |
| 138 | |
| 139 if (payload.distributedNodes) | |
| 140 this._setDistributedNodePayloads(payload.distributedNodes); | |
| 141 | |
| 142 if (payload.children) | |
| 143 this._setChildrenPayload(payload.children); | |
| 144 | |
| 145 this._setPseudoElements(payload.pseudoElements); | |
| 146 | |
| 147 if (payload.contentDocument) { | |
| 148 this._contentDocument = new WebInspector.DOMDocument(this._domModel,
payload.contentDocument); | |
| 149 this._children = [this._contentDocument]; | |
| 150 this._renumber(); | |
| 151 } | |
| 152 | |
| 153 if (this._nodeType === Node.ELEMENT_NODE) { | |
| 154 // HTML and BODY from internal iframes should not overwrite top-leve
l ones. | |
| 155 if (this.ownerDocument && !this.ownerDocument.documentElement && thi
s._nodeName === "HTML") | |
| 156 this.ownerDocument.documentElement = this; | |
| 157 if (this.ownerDocument && !this.ownerDocument.body && this._nodeName
=== "BODY") | |
| 158 this.ownerDocument.body = this; | |
| 159 } else if (this._nodeType === Node.DOCUMENT_TYPE_NODE) { | |
| 160 this.publicId = payload.publicId; | |
| 161 this.systemId = payload.systemId; | |
| 162 this.internalSubset = payload.internalSubset; | |
| 163 } else if (this._nodeType === Node.ATTRIBUTE_NODE) { | |
| 164 this.name = payload.name; | |
| 165 this.value = payload.value; | |
| 166 } | |
| 167 }, | |
| 168 | |
| 169 /** | |
| 170 * @return {!WebInspector.DOMModel} | |
| 171 */ | |
| 172 domModel: function() | |
| 173 { | |
| 174 return this._domModel; | |
| 175 }, | |
| 176 | |
| 177 /** | |
| 178 * @return {?Array.<!WebInspector.DOMNode>} | |
| 179 */ | |
| 180 children: function() | |
| 181 { | |
| 182 return this._children ? this._children.slice() : null; | |
| 183 }, | |
| 184 | |
| 185 /** | |
| 186 * @return {boolean} | |
| 187 */ | |
| 188 hasAttributes: function() | |
| 189 { | |
| 190 return this._attributes.length > 0; | |
| 191 }, | |
| 192 | |
| 193 /** | |
| 194 * @return {number} | |
| 195 */ | |
| 196 childNodeCount: function() | |
| 197 { | |
| 198 return this._childNodeCount; | |
| 199 }, | |
| 200 | |
| 201 /** | |
| 202 * @return {boolean} | |
| 203 */ | |
| 204 hasShadowRoots: function() | |
| 205 { | |
| 206 return !!this._shadowRoots.length; | |
| 207 }, | |
| 208 | |
| 209 /** | |
| 210 * @return {!Array.<!WebInspector.DOMNode>} | |
| 211 */ | |
| 212 shadowRoots: function() | |
| 213 { | |
| 214 return this._shadowRoots.slice(); | |
| 215 }, | |
| 216 | |
| 217 /** | |
| 218 * @return {?WebInspector.DOMNode} | |
| 219 */ | |
| 220 templateContent: function() | |
| 221 { | |
| 222 return this._templateContent || null; | |
| 223 }, | |
| 224 | |
| 225 /** | |
| 226 * @return {?WebInspector.DOMNode} | |
| 227 */ | |
| 228 importedDocument: function() | |
| 229 { | |
| 230 return this._importedDocument || null; | |
| 231 }, | |
| 232 | |
| 233 /** | |
| 234 * @return {number} | |
| 235 */ | |
| 236 nodeType: function() | |
| 237 { | |
| 238 return this._nodeType; | |
| 239 }, | |
| 240 | |
| 241 /** | |
| 242 * @return {string} | |
| 243 */ | |
| 244 nodeName: function() | |
| 245 { | |
| 246 return this._nodeName; | |
| 247 }, | |
| 248 | |
| 249 /** | |
| 250 * @return {string|undefined} | |
| 251 */ | |
| 252 pseudoType: function() | |
| 253 { | |
| 254 return this._pseudoType; | |
| 255 }, | |
| 256 | |
| 257 /** | |
| 258 * @return {boolean} | |
| 259 */ | |
| 260 hasPseudoElements: function() | |
| 261 { | |
| 262 return this._pseudoElements.size > 0; | |
| 263 }, | |
| 264 | |
| 265 /** | |
| 266 * @return {!Map<string, !WebInspector.DOMNode>} | |
| 267 */ | |
| 268 pseudoElements: function() | |
| 269 { | |
| 270 return this._pseudoElements; | |
| 271 }, | |
| 272 | |
| 273 /** | |
| 274 * @return {?WebInspector.DOMNode} | |
| 275 */ | |
| 276 beforePseudoElement: function() | |
| 277 { | |
| 278 if (!this._pseudoElements) | |
| 279 return null; | |
| 280 return this._pseudoElements.get(WebInspector.DOMNode.PseudoElementNames.
Before); | |
| 281 }, | |
| 282 | |
| 283 /** | |
| 284 * @return {?WebInspector.DOMNode} | |
| 285 */ | |
| 286 afterPseudoElement: function() | |
| 287 { | |
| 288 if (!this._pseudoElements) | |
| 289 return null; | |
| 290 return this._pseudoElements.get(WebInspector.DOMNode.PseudoElementNames.
After); | |
| 291 }, | |
| 292 | |
| 293 /** | |
| 294 * @return {boolean} | |
| 295 */ | |
| 296 isInsertionPoint: function() | |
| 297 { | |
| 298 return !this.isXMLNode() && (this._nodeName === "SHADOW" || this._nodeNa
me === "CONTENT" || this._nodeName === "SLOT"); | |
| 299 }, | |
| 300 | |
| 301 /** | |
| 302 * @return {!Array.<!WebInspector.DOMNodeShortcut>} | |
| 303 */ | |
| 304 distributedNodes: function() | |
| 305 { | |
| 306 return this._distributedNodes || []; | |
| 307 }, | |
| 308 | |
| 309 /** | |
| 310 * @return {boolean} | |
| 311 */ | |
| 312 isInShadowTree: function() | |
| 313 { | |
| 314 return this._isInShadowTree; | |
| 315 }, | |
| 316 | |
| 317 /** | |
| 318 * @return {?WebInspector.DOMNode} | |
| 319 */ | |
| 320 ancestorShadowHost: function() | |
| 321 { | |
| 322 var ancestorShadowRoot = this.ancestorShadowRoot(); | |
| 323 return ancestorShadowRoot ? ancestorShadowRoot.parentNode : null; | |
| 324 }, | |
| 325 | |
| 326 /** | |
| 327 * @return {?WebInspector.DOMNode} | |
| 328 */ | |
| 329 ancestorShadowRoot: function() | |
| 330 { | |
| 331 if (!this._isInShadowTree) | |
| 332 return null; | |
| 333 | |
| 334 var current = this; | |
| 335 while (current && !current.isShadowRoot()) | |
| 336 current = current.parentNode; | |
| 337 return current; | |
| 338 }, | |
| 339 | |
| 340 /** | |
| 341 * @return {?WebInspector.DOMNode} | |
| 342 */ | |
| 343 ancestorUserAgentShadowRoot: function() | |
| 344 { | |
| 345 var ancestorShadowRoot = this.ancestorShadowRoot(); | |
| 346 if (!ancestorShadowRoot) | |
| 347 return null; | |
| 348 return ancestorShadowRoot.shadowRootType() === WebInspector.DOMNode.Shad
owRootTypes.UserAgent ? ancestorShadowRoot : null; | |
| 349 }, | |
| 350 | |
| 351 /** | |
| 352 * @return {boolean} | |
| 353 */ | |
| 354 isShadowRoot: function() | |
| 355 { | |
| 356 return !!this._shadowRootType; | |
| 357 }, | |
| 358 | |
| 359 /** | |
| 360 * @return {?string} | |
| 361 */ | |
| 362 shadowRootType: function() | |
| 363 { | |
| 364 return this._shadowRootType || null; | |
| 365 }, | |
| 366 | |
| 367 /** | |
| 368 * @return {string} | |
| 369 */ | |
| 370 nodeNameInCorrectCase: function() | |
| 371 { | |
| 372 var shadowRootType = this.shadowRootType(); | |
| 373 if (shadowRootType) | |
| 374 return "#shadow-root (" + shadowRootType + ")"; | |
| 375 | |
| 376 // If there is no local name, it's case sensitive | |
| 377 if (!this.localName()) | |
| 378 return this.nodeName(); | |
| 379 | |
| 380 // If the names are different lengths, there is a prefix and it's case s
ensitive | |
| 381 if (this.localName().length !== this.nodeName().length) | |
| 382 return this.nodeName(); | |
| 383 | |
| 384 // Return the localname, which will be case insensitive if its an html n
ode | |
| 385 return this.localName(); | |
| 386 }, | |
| 387 | |
| 388 /** | |
| 389 * @param {string} name | |
| 390 * @param {function(?Protocol.Error, number)=} callback | |
| 391 */ | |
| 392 setNodeName: function(name, callback) | |
| 393 { | |
| 394 this._agent.setNodeName(this.id, name, this._domModel._markRevision(this
, callback)); | |
| 395 }, | |
| 396 | |
| 397 /** | |
| 398 * @return {string} | |
| 399 */ | |
| 400 localName: function() | |
| 401 { | |
| 402 return this._localName; | |
| 403 }, | |
| 404 | |
| 405 /** | |
| 406 * @return {string} | |
| 407 */ | |
| 408 nodeValue: function() | |
| 409 { | |
| 410 return this._nodeValue; | |
| 411 }, | |
| 412 | |
| 413 /** | |
| 414 * @param {string} value | |
| 415 * @param {function(?Protocol.Error)=} callback | |
| 416 */ | |
| 417 setNodeValue: function(value, callback) | |
| 418 { | |
| 419 this._agent.setNodeValue(this.id, value, this._domModel._markRevision(th
is, callback)); | |
| 420 }, | |
| 421 | |
| 422 /** | |
| 423 * @param {string} name | |
| 424 * @return {string} | |
| 425 */ | |
| 426 getAttribute: function(name) | |
| 427 { | |
| 428 var attr = this._attributesMap[name]; | |
| 429 return attr ? attr.value : undefined; | |
| 430 }, | |
| 431 | |
| 432 /** | |
| 433 * @param {string} name | |
| 434 * @param {string} text | |
| 435 * @param {function(?Protocol.Error)=} callback | |
| 436 */ | |
| 437 setAttribute: function(name, text, callback) | |
| 438 { | |
| 439 this._agent.setAttributesAsText(this.id, text, name, this._domModel._mar
kRevision(this, callback)); | |
| 440 }, | |
| 441 | |
| 442 /** | |
| 443 * @param {string} name | |
| 444 * @param {string} value | |
| 445 * @param {function(?Protocol.Error)=} callback | |
| 446 */ | |
| 447 setAttributeValue: function(name, value, callback) | |
| 448 { | |
| 449 this._agent.setAttributeValue(this.id, name, value, this._domModel._mark
Revision(this, callback)); | |
| 450 }, | |
| 451 | |
| 452 /** | |
| 453 * @return {!Array<!WebInspector.DOMNode.Attribute>} | |
| 454 */ | |
| 455 attributes: function() | |
| 456 { | |
| 457 return this._attributes; | |
| 458 }, | |
| 459 | |
| 460 /** | |
| 461 * @param {string} name | |
| 462 * @param {function(?Protocol.Error)=} callback | |
| 463 */ | |
| 464 removeAttribute: function(name, callback) | |
| 465 { | |
| 466 /** | |
| 467 * @param {?Protocol.Error} error | |
| 468 * @this {WebInspector.DOMNode} | |
| 469 */ | |
| 470 function mycallback(error) | |
| 471 { | |
| 472 if (!error) { | |
| 473 delete this._attributesMap[name]; | |
| 474 for (var i = 0; i < this._attributes.length; ++i) { | |
| 475 if (this._attributes[i].name === name) { | |
| 476 this._attributes.splice(i, 1); | |
| 477 break; | |
| 478 } | |
| 479 } | |
| 480 } | |
| 481 | |
| 482 this._domModel._markRevision(this, callback)(error); | |
| 483 } | |
| 484 this._agent.removeAttribute(this.id, name, mycallback.bind(this)); | |
| 485 }, | |
| 486 | |
| 487 /** | |
| 488 * @param {function(?Array.<!WebInspector.DOMNode>)=} callback | |
| 489 */ | |
| 490 getChildNodes: function(callback) | |
| 491 { | |
| 492 if (this._children) { | |
| 493 if (callback) | |
| 494 callback(this.children()); | |
| 495 return; | |
| 496 } | |
| 497 | |
| 498 /** | |
| 499 * @this {WebInspector.DOMNode} | |
| 500 * @param {?Protocol.Error} error | |
| 501 */ | |
| 502 function mycallback(error) | |
| 503 { | |
| 504 if (callback) | |
| 505 callback(error ? null : this.children()); | |
| 506 } | |
| 507 | |
| 508 this._agent.requestChildNodes(this.id, undefined, mycallback.bind(this))
; | |
| 509 }, | |
| 510 | |
| 511 /** | |
| 512 * @param {number} depth | |
| 513 * @param {function(?Array.<!WebInspector.DOMNode>)=} callback | |
| 514 */ | |
| 515 getSubtree: function(depth, callback) | |
| 516 { | |
| 517 /** | |
| 518 * @this {WebInspector.DOMNode} | |
| 519 * @param {?Protocol.Error} error | |
| 520 */ | |
| 521 function mycallback(error) | |
| 522 { | |
| 523 if (callback) | |
| 524 callback(error ? null : this._children); | |
| 525 } | |
| 526 | |
| 527 this._agent.requestChildNodes(this.id, depth, mycallback.bind(this)); | |
| 528 }, | |
| 529 | |
| 530 /** | |
| 531 * @param {function(?Protocol.Error, string)=} callback | |
| 532 */ | |
| 533 getOuterHTML: function(callback) | |
| 534 { | |
| 535 this._agent.getOuterHTML(this.id, callback); | |
| 536 }, | |
| 537 | |
| 538 /** | |
| 539 * @param {string} html | |
| 540 * @param {function(?Protocol.Error)=} callback | |
| 541 */ | |
| 542 setOuterHTML: function(html, callback) | |
| 543 { | |
| 544 this._agent.setOuterHTML(this.id, html, this._domModel._markRevision(thi
s, callback)); | |
| 545 }, | |
| 546 | |
| 547 /** | |
| 548 * @param {function(?Protocol.Error, !DOMAgent.NodeId=)=} callback | |
| 549 */ | |
| 550 removeNode: function(callback) | |
| 551 { | |
| 552 this._agent.removeNode(this.id, this._domModel._markRevision(this, callb
ack)); | |
| 553 }, | |
| 554 | |
| 555 /** | |
| 556 * @param {function(?string)=} callback | |
| 557 */ | |
| 558 copyNode: function(callback) | |
| 559 { | |
| 560 function copy(error, text) | |
| 561 { | |
| 562 if (!error) | |
| 563 InspectorFrontendHost.copyText(text); | |
| 564 if (callback) | |
| 565 callback(error ? null : text); | |
| 566 } | |
| 567 this._agent.getOuterHTML(this.id, copy); | |
| 568 }, | |
| 569 | |
| 570 /** | |
| 571 * @return {string} | |
| 572 */ | |
| 573 path: function() | |
| 574 { | |
| 575 /** | |
| 576 * @param {?WebInspector.DOMNode} node | |
| 577 */ | |
| 578 function canPush(node) | |
| 579 { | |
| 580 return node && ("index" in node || (node.isShadowRoot() && node.pare
ntNode)) && node._nodeName.length; | |
| 581 } | |
| 582 | |
| 583 var path = []; | |
| 584 var node = this; | |
| 585 while (canPush(node)) { | |
| 586 var index = typeof node.index === "number" ? node.index : (node.shad
owRootType() === WebInspector.DOMNode.ShadowRootTypes.UserAgent ? "u" : "a"); | |
| 587 path.push([index, node._nodeName]); | |
| 588 node = node.parentNode; | |
| 589 } | |
| 590 path.reverse(); | |
| 591 return path.join(","); | |
| 592 }, | |
| 593 | |
| 594 /** | |
| 595 * @param {!WebInspector.DOMNode} node | |
| 596 * @return {boolean} | |
| 597 */ | |
| 598 isAncestor: function(node) | |
| 599 { | |
| 600 if (!node) | |
| 601 return false; | |
| 602 | |
| 603 var currentNode = node.parentNode; | |
| 604 while (currentNode) { | |
| 605 if (this === currentNode) | |
| 606 return true; | |
| 607 currentNode = currentNode.parentNode; | |
| 608 } | |
| 609 return false; | |
| 610 }, | |
| 611 | |
| 612 /** | |
| 613 * @param {!WebInspector.DOMNode} descendant | |
| 614 * @return {boolean} | |
| 615 */ | |
| 616 isDescendant: function(descendant) | |
| 617 { | |
| 618 return descendant !== null && descendant.isAncestor(this); | |
| 619 }, | |
| 620 | |
| 621 /** | |
| 622 * @return {?PageAgent.FrameId} | |
| 623 */ | |
| 624 frameId: function() | |
| 625 { | |
| 626 var node = this.parentNode || this; | |
| 627 while (!node._frameOwnerFrameId && node.parentNode) | |
| 628 node = node.parentNode; | |
| 629 return node._frameOwnerFrameId; | |
| 630 }, | |
| 631 | |
| 632 /** | |
| 633 * @param {!Array.<string>} attrs | |
| 634 * @return {boolean} | |
| 635 */ | |
| 636 _setAttributesPayload: function(attrs) | |
| 637 { | |
| 638 var attributesChanged = !this._attributes || attrs.length !== this._attr
ibutes.length * 2; | |
| 639 var oldAttributesMap = this._attributesMap || {}; | |
| 640 | |
| 641 this._attributes = []; | |
| 642 this._attributesMap = {}; | |
| 643 | |
| 644 for (var i = 0; i < attrs.length; i += 2) { | |
| 645 var name = attrs[i]; | |
| 646 var value = attrs[i + 1]; | |
| 647 this._addAttribute(name, value); | |
| 648 | |
| 649 if (attributesChanged) | |
| 650 continue; | |
| 651 | |
| 652 if (!oldAttributesMap[name] || oldAttributesMap[name].value !== valu
e) | |
| 653 attributesChanged = true; | |
| 654 } | |
| 655 return attributesChanged; | |
| 656 }, | |
| 657 | |
| 658 /** | |
| 659 * @param {!WebInspector.DOMNode} prev | |
| 660 * @param {!DOMAgent.Node} payload | |
| 661 * @return {!WebInspector.DOMNode} | |
| 662 */ | |
| 663 _insertChild: function(prev, payload) | |
| 664 { | |
| 665 var node = WebInspector.DOMNode.create(this._domModel, this.ownerDocumen
t, this._isInShadowTree, payload); | |
| 666 this._children.splice(this._children.indexOf(prev) + 1, 0, node); | |
| 667 this._renumber(); | |
| 668 return node; | |
| 669 }, | |
| 670 | |
| 671 /** | |
| 672 * @param {!WebInspector.DOMNode} node | |
| 673 */ | |
| 674 _removeChild: function(node) | |
| 675 { | |
| 676 if (node.pseudoType()) { | |
| 677 this._pseudoElements.delete(node.pseudoType()); | |
| 678 } else { | |
| 679 var shadowRootIndex = this._shadowRoots.indexOf(node); | |
| 680 if (shadowRootIndex !== -1) { | |
| 681 this._shadowRoots.splice(shadowRootIndex, 1); | |
| 682 } else { | |
| 683 console.assert(this._children.indexOf(node) !== -1); | |
| 684 this._children.splice(this._children.indexOf(node), 1); | |
| 685 } | |
| 686 } | |
| 687 node.parentNode = null; | |
| 688 this._subtreeMarkerCount -= node._subtreeMarkerCount; | |
| 689 if (node._subtreeMarkerCount) | |
| 690 this._domModel.dispatchEventToListeners(WebInspector.DOMModel.Events
.MarkersChanged, this); | |
| 691 this._renumber(); | |
| 692 }, | |
| 693 | |
| 694 /** | |
| 695 * @param {!Array.<!DOMAgent.Node>} payloads | |
| 696 */ | |
| 697 _setChildrenPayload: function(payloads) | |
| 698 { | |
| 699 // We set children in the constructor. | |
| 700 if (this._contentDocument) | |
| 701 return; | |
| 702 | |
| 703 this._children = []; | |
| 704 for (var i = 0; i < payloads.length; ++i) { | |
| 705 var payload = payloads[i]; | |
| 706 var node = WebInspector.DOMNode.create(this._domModel, this.ownerDoc
ument, this._isInShadowTree, payload); | |
| 707 this._children.push(node); | |
| 708 } | |
| 709 this._renumber(); | |
| 710 }, | |
| 711 | |
| 712 /** | |
| 713 * @param {!Array.<!DOMAgent.Node>|undefined} payloads | |
| 714 */ | |
| 715 _setPseudoElements: function(payloads) | |
| 716 { | |
| 717 this._pseudoElements = new Map(); | |
| 718 if (!payloads) | |
| 719 return; | |
| 720 | |
| 721 for (var i = 0; i < payloads.length; ++i) { | |
| 722 var node = WebInspector.DOMNode.create(this._domModel, this.ownerDoc
ument, this._isInShadowTree, payloads[i]); | |
| 723 node.parentNode = this; | |
| 724 this._pseudoElements.set(node.pseudoType(), node); | |
| 725 } | |
| 726 }, | |
| 727 | |
| 728 /** | |
| 729 * @param {!Array.<!DOMAgent.BackendNode>} payloads | |
| 730 */ | |
| 731 _setDistributedNodePayloads: function(payloads) | |
| 732 { | |
| 733 this._distributedNodes = []; | |
| 734 for (var payload of payloads) | |
| 735 this._distributedNodes.push(new WebInspector.DOMNodeShortcut(this._d
omModel.target(), payload.backendNodeId, payload.nodeType, payload.nodeName)); | |
| 736 }, | |
| 737 | |
| 738 _renumber: function() | |
| 739 { | |
| 740 this._childNodeCount = this._children.length; | |
| 741 if (this._childNodeCount === 0) { | |
| 742 this.firstChild = null; | |
| 743 this.lastChild = null; | |
| 744 return; | |
| 745 } | |
| 746 this.firstChild = this._children[0]; | |
| 747 this.lastChild = this._children[this._childNodeCount - 1]; | |
| 748 for (var i = 0; i < this._childNodeCount; ++i) { | |
| 749 var child = this._children[i]; | |
| 750 child.index = i; | |
| 751 child.nextSibling = i + 1 < this._childNodeCount ? this._children[i
+ 1] : null; | |
| 752 child.previousSibling = i - 1 >= 0 ? this._children[i - 1] : null; | |
| 753 child.parentNode = this; | |
| 754 } | |
| 755 }, | |
| 756 | |
| 757 /** | |
| 758 * @param {string} name | |
| 759 * @param {string} value | |
| 760 */ | |
| 761 _addAttribute: function(name, value) | |
| 762 { | |
| 763 var attr = { | |
| 764 name: name, | |
| 765 value: value, | |
| 766 _node: this | |
| 767 }; | |
| 768 this._attributesMap[name] = attr; | |
| 769 this._attributes.push(attr); | |
| 770 }, | |
| 771 | |
| 772 /** | |
| 773 * @param {string} name | |
| 774 * @param {string} value | |
| 775 */ | |
| 776 _setAttribute: function(name, value) | |
| 777 { | |
| 778 var attr = this._attributesMap[name]; | |
| 779 if (attr) | |
| 780 attr.value = value; | |
| 781 else | |
| 782 this._addAttribute(name, value); | |
| 783 }, | |
| 784 | |
| 785 /** | |
| 786 * @param {string} name | |
| 787 */ | |
| 788 _removeAttribute: function(name) | |
| 789 { | |
| 790 var attr = this._attributesMap[name]; | |
| 791 if (attr) { | |
| 792 this._attributes.remove(attr); | |
| 793 delete this._attributesMap[name]; | |
| 794 } | |
| 795 }, | |
| 796 | |
| 797 /** | |
| 798 * @param {!WebInspector.DOMNode} targetNode | |
| 799 * @param {?WebInspector.DOMNode} anchorNode | |
| 800 * @param {function(?Protocol.Error, !DOMAgent.NodeId=)=} callback | |
| 801 */ | |
| 802 copyTo: function(targetNode, anchorNode, callback) | |
| 803 { | |
| 804 this._agent.copyTo(this.id, targetNode.id, anchorNode ? anchorNode.id :
undefined, this._domModel._markRevision(this, callback)); | |
| 805 }, | |
| 806 | |
| 807 /** | |
| 808 * @param {!WebInspector.DOMNode} targetNode | |
| 809 * @param {?WebInspector.DOMNode} anchorNode | |
| 810 * @param {function(?Protocol.Error, !DOMAgent.NodeId=)=} callback | |
| 811 */ | |
| 812 moveTo: function(targetNode, anchorNode, callback) | |
| 813 { | |
| 814 this._agent.moveTo(this.id, targetNode.id, anchorNode ? anchorNode.id :
undefined, this._domModel._markRevision(this, callback)); | |
| 815 }, | |
| 816 | |
| 817 /** | |
| 818 * @return {boolean} | |
| 819 */ | |
| 820 isXMLNode: function() | |
| 821 { | |
| 822 return !!this._xmlVersion; | |
| 823 }, | |
| 824 | |
| 825 /** | |
| 826 * @param {string} name | |
| 827 * @param {?*} value | |
| 828 */ | |
| 829 setMarker: function(name, value) | |
| 830 { | |
| 831 if (value === null) { | |
| 832 if (!this._markers.has(name)) | |
| 833 return; | |
| 834 | |
| 835 this._markers.delete(name); | |
| 836 for (var node = this; node; node = node.parentNode) | |
| 837 --node._subtreeMarkerCount; | |
| 838 for (var node = this; node; node = node.parentNode) | |
| 839 this._domModel.dispatchEventToListeners(WebInspector.DOMModel.Ev
ents.MarkersChanged, node); | |
| 840 return; | |
| 841 } | |
| 842 | |
| 843 if (this.parentNode && !this._markers.has(name)) { | |
| 844 for (var node = this; node; node = node.parentNode) | |
| 845 ++node._subtreeMarkerCount; | |
| 846 } | |
| 847 this._markers.set(name, value); | |
| 848 for (var node = this; node; node = node.parentNode) | |
| 849 this._domModel.dispatchEventToListeners(WebInspector.DOMModel.Events
.MarkersChanged, node); | |
| 850 }, | |
| 851 | |
| 852 /** | |
| 853 * @param {string} name | |
| 854 * @return {?T} | |
| 855 * @template T | |
| 856 */ | |
| 857 marker: function(name) | |
| 858 { | |
| 859 return this._markers.get(name) || null; | |
| 860 }, | |
| 861 | |
| 862 /** | |
| 863 * @param {function(!WebInspector.DOMNode, string)} visitor | |
| 864 */ | |
| 865 traverseMarkers: function(visitor) | |
| 866 { | |
| 867 /** | |
| 868 * @param {!WebInspector.DOMNode} node | |
| 869 */ | |
| 870 function traverse(node) | |
| 871 { | |
| 872 if (!node._subtreeMarkerCount) | |
| 873 return; | |
| 874 for (var marker of node._markers.keys()) | |
| 875 visitor(node, marker); | |
| 876 if (!node._children) | |
| 877 return; | |
| 878 for (var child of node._children) | |
| 879 traverse(child); | |
| 880 } | |
| 881 traverse(this); | |
| 882 }, | |
| 883 | |
| 884 /** | |
| 885 * @param {string} url | |
| 886 * @return {?string} | |
| 887 */ | |
| 888 resolveURL: function(url) | |
| 889 { | |
| 890 if (!url) | |
| 891 return url; | |
| 892 for (var frameOwnerCandidate = this; frameOwnerCandidate; frameOwnerCand
idate = frameOwnerCandidate.parentNode) { | |
| 893 if (frameOwnerCandidate.baseURL) | |
| 894 return WebInspector.ParsedURL.completeURL(frameOwnerCandidate.ba
seURL, url); | |
| 895 } | |
| 896 return null; | |
| 897 }, | |
| 898 | |
| 899 /** | |
| 900 * @param {string=} mode | |
| 901 * @param {!RuntimeAgent.RemoteObjectId=} objectId | |
| 902 */ | |
| 903 highlight: function(mode, objectId) | |
| 904 { | |
| 905 this._domModel.highlightDOMNode(this.id, mode, undefined, objectId); | |
| 906 }, | |
| 907 | |
| 908 highlightForTwoSeconds: function() | |
| 909 { | |
| 910 this._domModel.highlightDOMNodeForTwoSeconds(this.id); | |
| 911 }, | |
| 912 | |
| 913 /** | |
| 914 * @param {string=} objectGroup | |
| 915 * @param {function(?WebInspector.RemoteObject)=} callback | |
| 916 */ | |
| 917 resolveToObject: function(objectGroup, callback) | |
| 918 { | |
| 919 this._agent.resolveNode(this.id, objectGroup, mycallback.bind(this)); | |
| 920 | |
| 921 /** | |
| 922 * @param {?Protocol.Error} error | |
| 923 * @param {!RuntimeAgent.RemoteObject} object | |
| 924 * @this {WebInspector.DOMNode} | |
| 925 */ | |
| 926 function mycallback(error, object) | |
| 927 { | |
| 928 if (!callback) | |
| 929 return; | |
| 930 | |
| 931 if (error || !object) | |
| 932 callback(null); | |
| 933 else | |
| 934 callback(this.target().runtimeModel.createRemoteObject(object)); | |
| 935 } | |
| 936 }, | |
| 937 | |
| 938 /** | |
| 939 * @param {string=} objectGroup | |
| 940 * @return {!Promise<!WebInspector.RemoteObject>} | |
| 941 */ | |
| 942 resolveToObjectPromise: function(objectGroup) | |
| 943 { | |
| 944 return new Promise(resolveToObject.bind(this)); | |
| 945 /** | |
| 946 * @param {function(?)} fulfill | |
| 947 * @param {function(*)} reject | |
| 948 * @this {WebInspector.DOMNode} | |
| 949 */ | |
| 950 function resolveToObject(fulfill, reject) | |
| 951 { | |
| 952 this.resolveToObject(objectGroup, mycallback); | |
| 953 function mycallback(object) | |
| 954 { | |
| 955 if (object) | |
| 956 fulfill(object); | |
| 957 else | |
| 958 reject(null); | |
| 959 } | |
| 960 } | |
| 961 }, | |
| 962 | |
| 963 /** | |
| 964 * @param {function(?DOMAgent.BoxModel)} callback | |
| 965 */ | |
| 966 boxModel: function(callback) | |
| 967 { | |
| 968 this._agent.getBoxModel(this.id, this._domModel._wrapClientCallback(call
back)); | |
| 969 }, | |
| 970 | |
| 971 setAsInspectedNode: function() | |
| 972 { | |
| 973 var node = this; | |
| 974 while (true) { | |
| 975 var ancestor = node.ancestorUserAgentShadowRoot(); | |
| 976 if (!ancestor) | |
| 977 break; | |
| 978 ancestor = node.ancestorShadowHost(); | |
| 979 if (!ancestor) | |
| 980 break; | |
| 981 // User agent shadow root, keep climbing up. | |
| 982 node = ancestor; | |
| 983 } | |
| 984 this._agent.setInspectedNode(node.id); | |
| 985 }, | |
| 986 | |
| 987 /** | |
| 988 * @return {?WebInspector.DOMNode} | |
| 989 */ | |
| 990 enclosingElementOrSelf: function() | |
| 991 { | |
| 992 var node = this; | |
| 993 if (node && node.nodeType() === Node.TEXT_NODE && node.parentNode) | |
| 994 node = node.parentNode; | |
| 995 | |
| 996 if (node && node.nodeType() !== Node.ELEMENT_NODE) | |
| 997 node = null; | |
| 998 return node; | |
| 999 }, | |
| 1000 | |
| 1001 __proto__: WebInspector.SDKObject.prototype | |
| 1002 }; | |
| 1003 | |
| 1004 /** | 928 /** |
| 1005 * @param {!WebInspector.Target} target | 929 * @unrestricted |
| 1006 * @param {number} backendNodeId | |
| 1007 * @constructor | |
| 1008 */ | 930 */ |
| 1009 WebInspector.DeferredDOMNode = function(target, backendNodeId) | 931 WebInspector.DeferredDOMNode = class { |
| 1010 { | 932 /** |
| 933 * @param {!WebInspector.Target} target |
| 934 * @param {number} backendNodeId |
| 935 */ |
| 936 constructor(target, backendNodeId) { |
| 1011 this._domModel = WebInspector.DOMModel.fromTarget(target); | 937 this._domModel = WebInspector.DOMModel.fromTarget(target); |
| 1012 this._backendNodeId = backendNodeId; | 938 this._backendNodeId = backendNodeId; |
| 939 } |
| 940 |
| 941 /** |
| 942 * @param {function(?WebInspector.DOMNode)} callback |
| 943 */ |
| 944 resolve(callback) { |
| 945 if (!this._domModel) { |
| 946 callback(null); |
| 947 return; |
| 948 } |
| 949 |
| 950 this._domModel.pushNodesByBackendIdsToFrontend(new Set([this._backendNodeId]
), onGotNode.bind(this)); |
| 951 |
| 952 /** |
| 953 * @param {?Map<number, ?WebInspector.DOMNode>} nodeIds |
| 954 * @this {WebInspector.DeferredDOMNode} |
| 955 */ |
| 956 function onGotNode(nodeIds) { |
| 957 callback(nodeIds && (nodeIds.get(this._backendNodeId) || null)); |
| 958 } |
| 959 } |
| 960 |
| 961 /** |
| 962 * @return {!Promise.<!WebInspector.DOMNode>} |
| 963 */ |
| 964 resolvePromise() { |
| 965 /** |
| 966 * @param {function(?)} fulfill |
| 967 * @param {function(*)} reject |
| 968 * @this {WebInspector.DeferredDOMNode} |
| 969 */ |
| 970 function resolveNode(fulfill, reject) { |
| 971 /** |
| 972 * @param {?WebInspector.DOMNode} node |
| 973 */ |
| 974 function mycallback(node) { |
| 975 fulfill(node); |
| 976 } |
| 977 this.resolve(mycallback); |
| 978 } |
| 979 return new Promise(resolveNode.bind(this)); |
| 980 } |
| 981 |
| 982 /** |
| 983 * @return {number} |
| 984 */ |
| 985 backendNodeId() { |
| 986 return this._backendNodeId; |
| 987 } |
| 988 |
| 989 highlight() { |
| 990 if (this._domModel) |
| 991 this._domModel.highlightDOMNode(undefined, undefined, this._backendNodeId)
; |
| 992 } |
| 1013 }; | 993 }; |
| 1014 | 994 |
| 1015 WebInspector.DeferredDOMNode.prototype = { | |
| 1016 /** | |
| 1017 * @param {function(?WebInspector.DOMNode)} callback | |
| 1018 */ | |
| 1019 resolve: function(callback) | |
| 1020 { | |
| 1021 if (!this._domModel) { | |
| 1022 callback(null); | |
| 1023 return; | |
| 1024 } | |
| 1025 | |
| 1026 this._domModel.pushNodesByBackendIdsToFrontend(new Set([this._backendNod
eId]), onGotNode.bind(this)); | |
| 1027 | |
| 1028 /** | |
| 1029 * @param {?Map<number, ?WebInspector.DOMNode>} nodeIds | |
| 1030 * @this {WebInspector.DeferredDOMNode} | |
| 1031 */ | |
| 1032 function onGotNode(nodeIds) | |
| 1033 { | |
| 1034 callback(nodeIds && (nodeIds.get(this._backendNodeId) || null)); | |
| 1035 } | |
| 1036 }, | |
| 1037 | |
| 1038 /** | |
| 1039 * @return {!Promise.<!WebInspector.DOMNode>} | |
| 1040 */ | |
| 1041 resolvePromise: function() | |
| 1042 { | |
| 1043 /** | |
| 1044 * @param {function(?)} fulfill | |
| 1045 * @param {function(*)} reject | |
| 1046 * @this {WebInspector.DeferredDOMNode} | |
| 1047 */ | |
| 1048 function resolveNode(fulfill, reject) | |
| 1049 { | |
| 1050 /** | |
| 1051 * @param {?WebInspector.DOMNode} node | |
| 1052 */ | |
| 1053 function mycallback(node) | |
| 1054 { | |
| 1055 fulfill(node); | |
| 1056 } | |
| 1057 this.resolve(mycallback); | |
| 1058 } | |
| 1059 return new Promise(resolveNode.bind(this)); | |
| 1060 }, | |
| 1061 | |
| 1062 /** | |
| 1063 * @return {number} | |
| 1064 */ | |
| 1065 backendNodeId: function() | |
| 1066 { | |
| 1067 return this._backendNodeId; | |
| 1068 }, | |
| 1069 | |
| 1070 highlight: function() | |
| 1071 { | |
| 1072 if (this._domModel) | |
| 1073 this._domModel.highlightDOMNode(undefined, undefined, this._backendN
odeId); | |
| 1074 } | |
| 1075 }; | |
| 1076 | |
| 1077 /** | 995 /** |
| 1078 * @constructor | 996 * @unrestricted |
| 1079 * @param {!WebInspector.Target} target | |
| 1080 * @param {number} backendNodeId | |
| 1081 * @param {number} nodeType | |
| 1082 * @param {string} nodeName | |
| 1083 */ | 997 */ |
| 1084 WebInspector.DOMNodeShortcut = function(target, backendNodeId, nodeType, nodeNam
e) | 998 WebInspector.DOMNodeShortcut = class { |
| 1085 { | 999 /** |
| 1000 * @param {!WebInspector.Target} target |
| 1001 * @param {number} backendNodeId |
| 1002 * @param {number} nodeType |
| 1003 * @param {string} nodeName |
| 1004 */ |
| 1005 constructor(target, backendNodeId, nodeType, nodeName) { |
| 1086 this.nodeType = nodeType; | 1006 this.nodeType = nodeType; |
| 1087 this.nodeName = nodeName; | 1007 this.nodeName = nodeName; |
| 1088 this.deferredNode = new WebInspector.DeferredDOMNode(target, backendNodeId); | 1008 this.deferredNode = new WebInspector.DeferredDOMNode(target, backendNodeId); |
| 1009 } |
| 1089 }; | 1010 }; |
| 1090 | 1011 |
| 1091 /** | 1012 /** |
| 1092 * @extends {WebInspector.DOMNode} | 1013 * @unrestricted |
| 1093 * @constructor | |
| 1094 * @param {!WebInspector.DOMModel} domModel | |
| 1095 * @param {!DOMAgent.Node} payload | |
| 1096 */ | 1014 */ |
| 1097 WebInspector.DOMDocument = function(domModel, payload) | 1015 WebInspector.DOMDocument = class extends WebInspector.DOMNode { |
| 1098 { | 1016 /** |
| 1099 WebInspector.DOMNode.call(this, domModel); | 1017 * @param {!WebInspector.DOMModel} domModel |
| 1018 * @param {!DOMAgent.Node} payload |
| 1019 */ |
| 1020 constructor(domModel, payload) { |
| 1021 super(domModel); |
| 1100 this._init(this, false, payload); | 1022 this._init(this, false, payload); |
| 1101 this.documentURL = payload.documentURL || ""; | 1023 this.documentURL = payload.documentURL || ''; |
| 1102 this.baseURL = payload.baseURL || ""; | 1024 this.baseURL = payload.baseURL || ''; |
| 1103 this._listeners = {}; | 1025 this._listeners = {}; |
| 1026 } |
| 1104 }; | 1027 }; |
| 1105 | 1028 |
| 1106 WebInspector.DOMDocument.prototype = { | |
| 1107 __proto__: WebInspector.DOMNode.prototype | |
| 1108 }; | |
| 1109 | |
| 1110 /** | 1029 /** |
| 1111 * @constructor | 1030 * @unrestricted |
| 1112 * @extends {WebInspector.SDKModel} | |
| 1113 * @param {!WebInspector.Target} target | |
| 1114 */ | 1031 */ |
| 1115 WebInspector.DOMModel = function(target) { | 1032 WebInspector.DOMModel = class extends WebInspector.SDKModel { |
| 1116 WebInspector.SDKModel.call(this, WebInspector.DOMModel, target); | 1033 /** |
| 1034 * @param {!WebInspector.Target} target |
| 1035 */ |
| 1036 constructor(target) { |
| 1037 super(WebInspector.DOMModel, target); |
| 1117 | 1038 |
| 1118 this._agent = target.domAgent(); | 1039 this._agent = target.domAgent(); |
| 1119 | 1040 |
| 1120 /** @type {!Object.<number, !WebInspector.DOMNode>} */ | 1041 /** @type {!Object.<number, !WebInspector.DOMNode>} */ |
| 1121 this._idToDOMNode = {}; | 1042 this._idToDOMNode = {}; |
| 1122 /** @type {?WebInspector.DOMDocument} */ | 1043 /** @type {?WebInspector.DOMDocument} */ |
| 1123 this._document = null; | 1044 this._document = null; |
| 1124 /** @type {!Object.<number, boolean>} */ | 1045 /** @type {!Object.<number, boolean>} */ |
| 1125 this._attributeLoadNodeIds = {}; | 1046 this._attributeLoadNodeIds = {}; |
| 1126 target.registerDOMDispatcher(new WebInspector.DOMDispatcher(this)); | 1047 target.registerDOMDispatcher(new WebInspector.DOMDispatcher(this)); |
| 1127 | 1048 |
| 1128 this._inspectModeEnabled = false; | 1049 this._inspectModeEnabled = false; |
| 1129 | 1050 |
| 1130 this._defaultHighlighter = new WebInspector.DefaultDOMNodeHighlighter(this._
agent); | 1051 this._defaultHighlighter = new WebInspector.DefaultDOMNodeHighlighter(this._
agent); |
| 1131 this._highlighter = this._defaultHighlighter; | 1052 this._highlighter = this._defaultHighlighter; |
| 1132 | 1053 |
| 1133 this._agent.enable(); | 1054 this._agent.enable(); |
| 1055 } |
| 1056 |
| 1057 /** |
| 1058 * @param {!WebInspector.RemoteObject} object |
| 1059 */ |
| 1060 static highlightObjectAsDOMNode(object) { |
| 1061 var domModel = WebInspector.DOMModel.fromTarget(object.target()); |
| 1062 if (domModel) |
| 1063 domModel.highlightDOMNode(undefined, undefined, undefined, object.objectId
); |
| 1064 } |
| 1065 |
| 1066 /** |
| 1067 * @return {!Array<!WebInspector.DOMModel>} |
| 1068 */ |
| 1069 static instances() { |
| 1070 var result = []; |
| 1071 for (var target of WebInspector.targetManager.targets()) { |
| 1072 var domModel = WebInspector.DOMModel.fromTarget(target); |
| 1073 if (domModel) |
| 1074 result.push(domModel); |
| 1075 } |
| 1076 return result; |
| 1077 } |
| 1078 |
| 1079 static hideDOMNodeHighlight() { |
| 1080 for (var domModel of WebInspector.DOMModel.instances()) |
| 1081 domModel.highlightDOMNode(0); |
| 1082 } |
| 1083 |
| 1084 static muteHighlight() { |
| 1085 WebInspector.DOMModel.hideDOMNodeHighlight(); |
| 1086 WebInspector.DOMModel._highlightDisabled = true; |
| 1087 } |
| 1088 |
| 1089 static unmuteHighlight() { |
| 1090 WebInspector.DOMModel._highlightDisabled = false; |
| 1091 } |
| 1092 |
| 1093 static cancelSearch() { |
| 1094 for (var domModel of WebInspector.DOMModel.instances()) |
| 1095 domModel._cancelSearch(); |
| 1096 } |
| 1097 |
| 1098 /** |
| 1099 * @param {!WebInspector.Target} target |
| 1100 * @return {?WebInspector.DOMModel} |
| 1101 */ |
| 1102 static fromTarget(target) { |
| 1103 return /** @type {?WebInspector.DOMModel} */ (target.model(WebInspector.DOMM
odel)); |
| 1104 } |
| 1105 |
| 1106 /** |
| 1107 * @param {!WebInspector.DOMNode} node |
| 1108 */ |
| 1109 _scheduleMutationEvent(node) { |
| 1110 if (!this.hasEventListeners(WebInspector.DOMModel.Events.DOMMutated)) |
| 1111 return; |
| 1112 |
| 1113 this._lastMutationId = (this._lastMutationId || 0) + 1; |
| 1114 Promise.resolve().then(callObserve.bind(this, node, this._lastMutationId)); |
| 1115 |
| 1116 /** |
| 1117 * @this {WebInspector.DOMModel} |
| 1118 * @param {!WebInspector.DOMNode} node |
| 1119 * @param {number} mutationId |
| 1120 */ |
| 1121 function callObserve(node, mutationId) { |
| 1122 if (!this.hasEventListeners(WebInspector.DOMModel.Events.DOMMutated) || th
is._lastMutationId !== mutationId) |
| 1123 return; |
| 1124 |
| 1125 this.dispatchEventToListeners(WebInspector.DOMModel.Events.DOMMutated, nod
e); |
| 1126 } |
| 1127 } |
| 1128 |
| 1129 /** |
| 1130 * @param {function(!WebInspector.DOMDocument)=} callback |
| 1131 */ |
| 1132 requestDocument(callback) { |
| 1133 if (this._document) { |
| 1134 if (callback) |
| 1135 callback(this._document); |
| 1136 return; |
| 1137 } |
| 1138 |
| 1139 if (this._pendingDocumentRequestCallbacks) { |
| 1140 this._pendingDocumentRequestCallbacks.push(callback); |
| 1141 return; |
| 1142 } |
| 1143 |
| 1144 this._pendingDocumentRequestCallbacks = [callback]; |
| 1145 |
| 1146 /** |
| 1147 * @this {WebInspector.DOMModel} |
| 1148 * @param {?Protocol.Error} error |
| 1149 * @param {!DOMAgent.Node} root |
| 1150 */ |
| 1151 function onDocumentAvailable(error, root) { |
| 1152 if (!error) |
| 1153 this._setDocument(root); |
| 1154 |
| 1155 for (var i = 0; i < this._pendingDocumentRequestCallbacks.length; ++i) { |
| 1156 var callback = this._pendingDocumentRequestCallbacks[i]; |
| 1157 if (callback) |
| 1158 callback(this._document); |
| 1159 } |
| 1160 delete this._pendingDocumentRequestCallbacks; |
| 1161 } |
| 1162 |
| 1163 this._agent.getDocument(undefined, undefined, onDocumentAvailable.bind(this)
); |
| 1164 } |
| 1165 |
| 1166 /** |
| 1167 * @return {?WebInspector.DOMDocument} |
| 1168 */ |
| 1169 existingDocument() { |
| 1170 return this._document; |
| 1171 } |
| 1172 |
| 1173 /** |
| 1174 * @param {!RuntimeAgent.RemoteObjectId} objectId |
| 1175 * @param {function(?WebInspector.DOMNode)=} callback |
| 1176 */ |
| 1177 pushNodeToFrontend(objectId, callback) { |
| 1178 /** |
| 1179 * @param {?DOMAgent.NodeId} nodeId |
| 1180 * @this {!WebInspector.DOMModel} |
| 1181 */ |
| 1182 function mycallback(nodeId) { |
| 1183 callback(nodeId ? this.nodeForId(nodeId) : null); |
| 1184 } |
| 1185 this._dispatchWhenDocumentAvailable(this._agent.requestNode.bind(this._agent
, objectId), mycallback.bind(this)); |
| 1186 } |
| 1187 |
| 1188 /** |
| 1189 * @param {string} path |
| 1190 * @param {function(?number)=} callback |
| 1191 */ |
| 1192 pushNodeByPathToFrontend(path, callback) { |
| 1193 this._dispatchWhenDocumentAvailable(this._agent.pushNodeByPathToFrontend.bin
d(this._agent, path), callback); |
| 1194 } |
| 1195 |
| 1196 /** |
| 1197 * @param {!Set<number>} backendNodeIds |
| 1198 * @param {function(?Map<number, ?WebInspector.DOMNode>)} callback |
| 1199 */ |
| 1200 pushNodesByBackendIdsToFrontend(backendNodeIds, callback) { |
| 1201 var backendNodeIdsArray = backendNodeIds.valuesArray(); |
| 1202 /** |
| 1203 * @param {?Array<!DOMAgent.NodeId>} nodeIds |
| 1204 * @this {!WebInspector.DOMModel} |
| 1205 */ |
| 1206 function mycallback(nodeIds) { |
| 1207 if (!nodeIds) { |
| 1208 callback(null); |
| 1209 return; |
| 1210 } |
| 1211 /** @type {!Map<number, ?WebInspector.DOMNode>} */ |
| 1212 var map = new Map(); |
| 1213 for (var i = 0; i < nodeIds.length; ++i) { |
| 1214 if (nodeIds[i]) |
| 1215 map.set(backendNodeIdsArray[i], this.nodeForId(nodeIds[i])); |
| 1216 } |
| 1217 callback(map); |
| 1218 } |
| 1219 this._dispatchWhenDocumentAvailable( |
| 1220 this._agent.pushNodesByBackendIdsToFrontend.bind(this._agent, backendNod
eIdsArray), mycallback.bind(this)); |
| 1221 } |
| 1222 |
| 1223 /** |
| 1224 * @param {function(!T)=} callback |
| 1225 * @return {function(?Protocol.Error, !T=)|undefined} |
| 1226 * @template T |
| 1227 */ |
| 1228 _wrapClientCallback(callback) { |
| 1229 if (!callback) |
| 1230 return; |
| 1231 /** |
| 1232 * @param {?Protocol.Error} error |
| 1233 * @param {!T=} result |
| 1234 * @template T |
| 1235 */ |
| 1236 var wrapper = function(error, result) { |
| 1237 // Caller is responsible for handling the actual error. |
| 1238 callback(error ? null : result); |
| 1239 }; |
| 1240 return wrapper; |
| 1241 } |
| 1242 |
| 1243 /** |
| 1244 * @param {function(function(?Protocol.Error, !T=)=)} func |
| 1245 * @param {function(!T)=} callback |
| 1246 * @template T |
| 1247 */ |
| 1248 _dispatchWhenDocumentAvailable(func, callback) { |
| 1249 var callbackWrapper = this._wrapClientCallback(callback); |
| 1250 |
| 1251 /** |
| 1252 * @this {WebInspector.DOMModel} |
| 1253 */ |
| 1254 function onDocumentAvailable() { |
| 1255 if (this._document) |
| 1256 func(callbackWrapper); |
| 1257 else { |
| 1258 if (callbackWrapper) |
| 1259 callbackWrapper('No document'); |
| 1260 } |
| 1261 } |
| 1262 this.requestDocument(onDocumentAvailable.bind(this)); |
| 1263 } |
| 1264 |
| 1265 /** |
| 1266 * @param {!DOMAgent.NodeId} nodeId |
| 1267 * @param {string} name |
| 1268 * @param {string} value |
| 1269 */ |
| 1270 _attributeModified(nodeId, name, value) { |
| 1271 var node = this._idToDOMNode[nodeId]; |
| 1272 if (!node) |
| 1273 return; |
| 1274 |
| 1275 node._setAttribute(name, value); |
| 1276 this.dispatchEventToListeners(WebInspector.DOMModel.Events.AttrModified, {no
de: node, name: name}); |
| 1277 this._scheduleMutationEvent(node); |
| 1278 } |
| 1279 |
| 1280 /** |
| 1281 * @param {!DOMAgent.NodeId} nodeId |
| 1282 * @param {string} name |
| 1283 */ |
| 1284 _attributeRemoved(nodeId, name) { |
| 1285 var node = this._idToDOMNode[nodeId]; |
| 1286 if (!node) |
| 1287 return; |
| 1288 node._removeAttribute(name); |
| 1289 this.dispatchEventToListeners(WebInspector.DOMModel.Events.AttrRemoved, {nod
e: node, name: name}); |
| 1290 this._scheduleMutationEvent(node); |
| 1291 } |
| 1292 |
| 1293 /** |
| 1294 * @param {!Array.<!DOMAgent.NodeId>} nodeIds |
| 1295 */ |
| 1296 _inlineStyleInvalidated(nodeIds) { |
| 1297 for (var i = 0; i < nodeIds.length; ++i) |
| 1298 this._attributeLoadNodeIds[nodeIds[i]] = true; |
| 1299 if ('_loadNodeAttributesTimeout' in this) |
| 1300 return; |
| 1301 this._loadNodeAttributesTimeout = setTimeout(this._loadNodeAttributes.bind(t
his), 20); |
| 1302 } |
| 1303 |
| 1304 _loadNodeAttributes() { |
| 1305 /** |
| 1306 * @this {WebInspector.DOMModel} |
| 1307 * @param {!DOMAgent.NodeId} nodeId |
| 1308 * @param {?Protocol.Error} error |
| 1309 * @param {!Array.<string>} attributes |
| 1310 */ |
| 1311 function callback(nodeId, error, attributes) { |
| 1312 if (error) { |
| 1313 // We are calling _loadNodeAttributes asynchronously, it is ok if node i
s not found. |
| 1314 return; |
| 1315 } |
| 1316 var node = this._idToDOMNode[nodeId]; |
| 1317 if (node) { |
| 1318 if (node._setAttributesPayload(attributes)) { |
| 1319 this.dispatchEventToListeners(WebInspector.DOMModel.Events.AttrModifie
d, {node: node, name: 'style'}); |
| 1320 this._scheduleMutationEvent(node); |
| 1321 } |
| 1322 } |
| 1323 } |
| 1324 |
| 1325 delete this._loadNodeAttributesTimeout; |
| 1326 |
| 1327 for (var nodeId in this._attributeLoadNodeIds) { |
| 1328 var nodeIdAsNumber = parseInt(nodeId, 10); |
| 1329 this._agent.getAttributes(nodeIdAsNumber, callback.bind(this, nodeIdAsNumb
er)); |
| 1330 } |
| 1331 this._attributeLoadNodeIds = {}; |
| 1332 } |
| 1333 |
| 1334 /** |
| 1335 * @param {!DOMAgent.NodeId} nodeId |
| 1336 * @param {string} newValue |
| 1337 */ |
| 1338 _characterDataModified(nodeId, newValue) { |
| 1339 var node = this._idToDOMNode[nodeId]; |
| 1340 node._nodeValue = newValue; |
| 1341 this.dispatchEventToListeners(WebInspector.DOMModel.Events.CharacterDataModi
fied, node); |
| 1342 this._scheduleMutationEvent(node); |
| 1343 } |
| 1344 |
| 1345 /** |
| 1346 * @param {!DOMAgent.NodeId} nodeId |
| 1347 * @return {?WebInspector.DOMNode} |
| 1348 */ |
| 1349 nodeForId(nodeId) { |
| 1350 return this._idToDOMNode[nodeId] || null; |
| 1351 } |
| 1352 |
| 1353 _documentUpdated() { |
| 1354 this._setDocument(null); |
| 1355 } |
| 1356 |
| 1357 /** |
| 1358 * @param {?DOMAgent.Node} payload |
| 1359 */ |
| 1360 _setDocument(payload) { |
| 1361 this._idToDOMNode = {}; |
| 1362 if (payload && 'nodeId' in payload) |
| 1363 this._document = new WebInspector.DOMDocument(this, payload); |
| 1364 else |
| 1365 this._document = null; |
| 1366 this.dispatchEventToListeners(WebInspector.DOMModel.Events.DocumentUpdated,
this._document); |
| 1367 } |
| 1368 |
| 1369 /** |
| 1370 * @param {!DOMAgent.Node} payload |
| 1371 */ |
| 1372 _setDetachedRoot(payload) { |
| 1373 if (payload.nodeName === '#document') |
| 1374 new WebInspector.DOMDocument(this, payload); |
| 1375 else |
| 1376 WebInspector.DOMNode.create(this, null, false, payload); |
| 1377 } |
| 1378 |
| 1379 /** |
| 1380 * @param {!DOMAgent.NodeId} parentId |
| 1381 * @param {!Array.<!DOMAgent.Node>} payloads |
| 1382 */ |
| 1383 _setChildNodes(parentId, payloads) { |
| 1384 if (!parentId && payloads.length) { |
| 1385 this._setDetachedRoot(payloads[0]); |
| 1386 return; |
| 1387 } |
| 1388 |
| 1389 var parent = this._idToDOMNode[parentId]; |
| 1390 parent._setChildrenPayload(payloads); |
| 1391 } |
| 1392 |
| 1393 /** |
| 1394 * @param {!DOMAgent.NodeId} nodeId |
| 1395 * @param {number} newValue |
| 1396 */ |
| 1397 _childNodeCountUpdated(nodeId, newValue) { |
| 1398 var node = this._idToDOMNode[nodeId]; |
| 1399 node._childNodeCount = newValue; |
| 1400 this.dispatchEventToListeners(WebInspector.DOMModel.Events.ChildNodeCountUpd
ated, node); |
| 1401 this._scheduleMutationEvent(node); |
| 1402 } |
| 1403 |
| 1404 /** |
| 1405 * @param {!DOMAgent.NodeId} parentId |
| 1406 * @param {!DOMAgent.NodeId} prevId |
| 1407 * @param {!DOMAgent.Node} payload |
| 1408 */ |
| 1409 _childNodeInserted(parentId, prevId, payload) { |
| 1410 var parent = this._idToDOMNode[parentId]; |
| 1411 var prev = this._idToDOMNode[prevId]; |
| 1412 var node = parent._insertChild(prev, payload); |
| 1413 this._idToDOMNode[node.id] = node; |
| 1414 this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeInserted, nod
e); |
| 1415 this._scheduleMutationEvent(node); |
| 1416 } |
| 1417 |
| 1418 /** |
| 1419 * @param {!DOMAgent.NodeId} parentId |
| 1420 * @param {!DOMAgent.NodeId} nodeId |
| 1421 */ |
| 1422 _childNodeRemoved(parentId, nodeId) { |
| 1423 var parent = this._idToDOMNode[parentId]; |
| 1424 var node = this._idToDOMNode[nodeId]; |
| 1425 parent._removeChild(node); |
| 1426 this._unbind(node); |
| 1427 this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeRemoved, {nod
e: node, parent: parent}); |
| 1428 this._scheduleMutationEvent(node); |
| 1429 } |
| 1430 |
| 1431 /** |
| 1432 * @param {!DOMAgent.NodeId} hostId |
| 1433 * @param {!DOMAgent.Node} root |
| 1434 */ |
| 1435 _shadowRootPushed(hostId, root) { |
| 1436 var host = this._idToDOMNode[hostId]; |
| 1437 if (!host) |
| 1438 return; |
| 1439 var node = WebInspector.DOMNode.create(this, host.ownerDocument, true, root)
; |
| 1440 node.parentNode = host; |
| 1441 this._idToDOMNode[node.id] = node; |
| 1442 host._shadowRoots.unshift(node); |
| 1443 this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeInserted, nod
e); |
| 1444 this._scheduleMutationEvent(node); |
| 1445 } |
| 1446 |
| 1447 /** |
| 1448 * @param {!DOMAgent.NodeId} hostId |
| 1449 * @param {!DOMAgent.NodeId} rootId |
| 1450 */ |
| 1451 _shadowRootPopped(hostId, rootId) { |
| 1452 var host = this._idToDOMNode[hostId]; |
| 1453 if (!host) |
| 1454 return; |
| 1455 var root = this._idToDOMNode[rootId]; |
| 1456 if (!root) |
| 1457 return; |
| 1458 host._removeChild(root); |
| 1459 this._unbind(root); |
| 1460 this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeRemoved, {nod
e: root, parent: host}); |
| 1461 this._scheduleMutationEvent(root); |
| 1462 } |
| 1463 |
| 1464 /** |
| 1465 * @param {!DOMAgent.NodeId} parentId |
| 1466 * @param {!DOMAgent.Node} pseudoElement |
| 1467 */ |
| 1468 _pseudoElementAdded(parentId, pseudoElement) { |
| 1469 var parent = this._idToDOMNode[parentId]; |
| 1470 if (!parent) |
| 1471 return; |
| 1472 var node = WebInspector.DOMNode.create(this, parent.ownerDocument, false, ps
eudoElement); |
| 1473 node.parentNode = parent; |
| 1474 this._idToDOMNode[node.id] = node; |
| 1475 console.assert(!parent._pseudoElements.get(node.pseudoType())); |
| 1476 parent._pseudoElements.set(node.pseudoType(), node); |
| 1477 this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeInserted, nod
e); |
| 1478 this._scheduleMutationEvent(node); |
| 1479 } |
| 1480 |
| 1481 /** |
| 1482 * @param {!DOMAgent.NodeId} parentId |
| 1483 * @param {!DOMAgent.NodeId} pseudoElementId |
| 1484 */ |
| 1485 _pseudoElementRemoved(parentId, pseudoElementId) { |
| 1486 var parent = this._idToDOMNode[parentId]; |
| 1487 if (!parent) |
| 1488 return; |
| 1489 var pseudoElement = this._idToDOMNode[pseudoElementId]; |
| 1490 if (!pseudoElement) |
| 1491 return; |
| 1492 parent._removeChild(pseudoElement); |
| 1493 this._unbind(pseudoElement); |
| 1494 this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeRemoved, {nod
e: pseudoElement, parent: parent}); |
| 1495 this._scheduleMutationEvent(pseudoElement); |
| 1496 } |
| 1497 |
| 1498 /** |
| 1499 * @param {!DOMAgent.NodeId} insertionPointId |
| 1500 * @param {!Array.<!DOMAgent.BackendNode>} distributedNodes |
| 1501 */ |
| 1502 _distributedNodesUpdated(insertionPointId, distributedNodes) { |
| 1503 var insertionPoint = this._idToDOMNode[insertionPointId]; |
| 1504 if (!insertionPoint) |
| 1505 return; |
| 1506 insertionPoint._setDistributedNodePayloads(distributedNodes); |
| 1507 this.dispatchEventToListeners(WebInspector.DOMModel.Events.DistributedNodesC
hanged, insertionPoint); |
| 1508 this._scheduleMutationEvent(insertionPoint); |
| 1509 } |
| 1510 |
| 1511 /** |
| 1512 * @param {!WebInspector.DOMNode} node |
| 1513 */ |
| 1514 _unbind(node) { |
| 1515 delete this._idToDOMNode[node.id]; |
| 1516 for (var i = 0; node._children && i < node._children.length; ++i) |
| 1517 this._unbind(node._children[i]); |
| 1518 for (var i = 0; i < node._shadowRoots.length; ++i) |
| 1519 this._unbind(node._shadowRoots[i]); |
| 1520 var pseudoElements = node.pseudoElements(); |
| 1521 for (var value of pseudoElements.values()) |
| 1522 this._unbind(value); |
| 1523 if (node._templateContent) |
| 1524 this._unbind(node._templateContent); |
| 1525 } |
| 1526 |
| 1527 /** |
| 1528 * @param {!DOMAgent.BackendNodeId} backendNodeId |
| 1529 */ |
| 1530 _inspectNodeRequested(backendNodeId) { |
| 1531 var deferredNode = new WebInspector.DeferredDOMNode(this.target(), backendNo
deId); |
| 1532 this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeInspected, de
ferredNode); |
| 1533 } |
| 1534 |
| 1535 /** |
| 1536 * @param {string} query |
| 1537 * @param {boolean} includeUserAgentShadowDOM |
| 1538 * @param {function(number)} searchCallback |
| 1539 */ |
| 1540 performSearch(query, includeUserAgentShadowDOM, searchCallback) { |
| 1541 WebInspector.DOMModel.cancelSearch(); |
| 1542 |
| 1543 /** |
| 1544 * @param {?Protocol.Error} error |
| 1545 * @param {string} searchId |
| 1546 * @param {number} resultsCount |
| 1547 * @this {WebInspector.DOMModel} |
| 1548 */ |
| 1549 function callback(error, searchId, resultsCount) { |
| 1550 this._searchId = searchId; |
| 1551 searchCallback(resultsCount); |
| 1552 } |
| 1553 this._agent.performSearch(query, includeUserAgentShadowDOM, callback.bind(th
is)); |
| 1554 } |
| 1555 |
| 1556 /** |
| 1557 * @param {string} query |
| 1558 * @param {boolean} includeUserAgentShadowDOM |
| 1559 * @return {!Promise.<number>} |
| 1560 */ |
| 1561 performSearchPromise(query, includeUserAgentShadowDOM) { |
| 1562 return new Promise(performSearch.bind(this)); |
| 1563 |
| 1564 /** |
| 1565 * @param {function(number)} resolve |
| 1566 * @this {WebInspector.DOMModel} |
| 1567 */ |
| 1568 function performSearch(resolve) { |
| 1569 this._agent.performSearch(query, includeUserAgentShadowDOM, callback.bind(
this)); |
| 1570 |
| 1571 /** |
| 1572 * @param {?Protocol.Error} error |
| 1573 * @param {string} searchId |
| 1574 * @param {number} resultsCount |
| 1575 * @this {WebInspector.DOMModel} |
| 1576 */ |
| 1577 function callback(error, searchId, resultsCount) { |
| 1578 if (!error) |
| 1579 this._searchId = searchId; |
| 1580 resolve(error ? 0 : resultsCount); |
| 1581 } |
| 1582 } |
| 1583 } |
| 1584 |
| 1585 /** |
| 1586 * @param {number} index |
| 1587 * @param {?function(?WebInspector.DOMNode)} callback |
| 1588 */ |
| 1589 searchResult(index, callback) { |
| 1590 if (this._searchId) |
| 1591 this._agent.getSearchResults(this._searchId, index, index + 1, searchResul
tsCallback.bind(this)); |
| 1592 else |
| 1593 callback(null); |
| 1594 |
| 1595 /** |
| 1596 * @param {?Protocol.Error} error |
| 1597 * @param {!Array.<number>} nodeIds |
| 1598 * @this {WebInspector.DOMModel} |
| 1599 */ |
| 1600 function searchResultsCallback(error, nodeIds) { |
| 1601 if (error) { |
| 1602 console.error(error); |
| 1603 callback(null); |
| 1604 return; |
| 1605 } |
| 1606 if (nodeIds.length !== 1) |
| 1607 return; |
| 1608 |
| 1609 callback(this.nodeForId(nodeIds[0])); |
| 1610 } |
| 1611 } |
| 1612 |
| 1613 _cancelSearch() { |
| 1614 if (this._searchId) { |
| 1615 this._agent.discardSearchResults(this._searchId); |
| 1616 delete this._searchId; |
| 1617 } |
| 1618 } |
| 1619 |
| 1620 /** |
| 1621 * @param {!DOMAgent.NodeId} nodeId |
| 1622 * @return {!Promise<!Array<string>>} |
| 1623 */ |
| 1624 classNamesPromise(nodeId) { |
| 1625 return new Promise(promiseBody.bind(this)); |
| 1626 |
| 1627 /** |
| 1628 * @param {function(!Array<string>)} fulfill |
| 1629 * @this {WebInspector.DOMModel} |
| 1630 */ |
| 1631 function promiseBody(fulfill) { |
| 1632 this._agent.collectClassNamesFromSubtree(nodeId, classNamesCallback); |
| 1633 |
| 1634 /** |
| 1635 * @param {?string} error |
| 1636 * @param {?Array<string>} classNames |
| 1637 */ |
| 1638 function classNamesCallback(error, classNames) { |
| 1639 if (!error && classNames) |
| 1640 fulfill(classNames); |
| 1641 else |
| 1642 fulfill([]); |
| 1643 } |
| 1644 } |
| 1645 } |
| 1646 |
| 1647 /** |
| 1648 * @param {!DOMAgent.NodeId} nodeId |
| 1649 * @param {string} selectors |
| 1650 * @param {function(?DOMAgent.NodeId)=} callback |
| 1651 */ |
| 1652 querySelector(nodeId, selectors, callback) { |
| 1653 this._agent.querySelector(nodeId, selectors, this._wrapClientCallback(callba
ck)); |
| 1654 } |
| 1655 |
| 1656 /** |
| 1657 * @param {!DOMAgent.NodeId} nodeId |
| 1658 * @param {string} selectors |
| 1659 * @param {function(!Array.<!DOMAgent.NodeId>=)=} callback |
| 1660 */ |
| 1661 querySelectorAll(nodeId, selectors, callback) { |
| 1662 this._agent.querySelectorAll(nodeId, selectors, this._wrapClientCallback(cal
lback)); |
| 1663 } |
| 1664 |
| 1665 /** |
| 1666 * @param {!DOMAgent.NodeId=} nodeId |
| 1667 * @param {string=} mode |
| 1668 * @param {!DOMAgent.BackendNodeId=} backendNodeId |
| 1669 * @param {!RuntimeAgent.RemoteObjectId=} objectId |
| 1670 */ |
| 1671 highlightDOMNode(nodeId, mode, backendNodeId, objectId) { |
| 1672 this.highlightDOMNodeWithConfig(nodeId, {mode: mode}, backendNodeId, objectI
d); |
| 1673 } |
| 1674 |
| 1675 /** |
| 1676 * @param {!DOMAgent.NodeId=} nodeId |
| 1677 * @param {!{mode: (string|undefined), showInfo: (boolean|undefined), selector
s: (string|undefined)}=} config |
| 1678 * @param {!DOMAgent.BackendNodeId=} backendNodeId |
| 1679 * @param {!RuntimeAgent.RemoteObjectId=} objectId |
| 1680 */ |
| 1681 highlightDOMNodeWithConfig(nodeId, config, backendNodeId, objectId) { |
| 1682 if (WebInspector.DOMModel._highlightDisabled) |
| 1683 return; |
| 1684 config = config || {mode: 'all', showInfo: undefined, selectors: undefined}; |
| 1685 if (this._hideDOMNodeHighlightTimeout) { |
| 1686 clearTimeout(this._hideDOMNodeHighlightTimeout); |
| 1687 delete this._hideDOMNodeHighlightTimeout; |
| 1688 } |
| 1689 var highlightConfig = this._buildHighlightConfig(config.mode); |
| 1690 if (typeof config.showInfo !== 'undefined') |
| 1691 highlightConfig.showInfo = config.showInfo; |
| 1692 if (typeof config.selectors !== 'undefined') |
| 1693 highlightConfig.selectorList = config.selectors; |
| 1694 this._highlighter.highlightDOMNode(this.nodeForId(nodeId || 0), highlightCon
fig, backendNodeId, objectId); |
| 1695 } |
| 1696 |
| 1697 /** |
| 1698 * @param {!DOMAgent.NodeId} nodeId |
| 1699 */ |
| 1700 highlightDOMNodeForTwoSeconds(nodeId) { |
| 1701 this.highlightDOMNode(nodeId); |
| 1702 this._hideDOMNodeHighlightTimeout = |
| 1703 setTimeout(WebInspector.DOMModel.hideDOMNodeHighlight.bind(WebInspector.
DOMModel), 2000); |
| 1704 } |
| 1705 |
| 1706 /** |
| 1707 * @param {!PageAgent.FrameId} frameId |
| 1708 */ |
| 1709 highlightFrame(frameId) { |
| 1710 if (WebInspector.DOMModel._highlightDisabled) |
| 1711 return; |
| 1712 this._highlighter.highlightFrame(frameId); |
| 1713 } |
| 1714 |
| 1715 /** |
| 1716 * @param {!DOMAgent.InspectMode} mode |
| 1717 * @param {function(?Protocol.Error)=} callback |
| 1718 */ |
| 1719 setInspectMode(mode, callback) { |
| 1720 /** |
| 1721 * @this {WebInspector.DOMModel} |
| 1722 */ |
| 1723 function onDocumentAvailable() { |
| 1724 this._inspectModeEnabled = mode !== DOMAgent.InspectMode.None; |
| 1725 this.dispatchEventToListeners(WebInspector.DOMModel.Events.InspectModeWill
BeToggled, this._inspectModeEnabled); |
| 1726 this._highlighter.setInspectMode(mode, this._buildHighlightConfig(), callb
ack); |
| 1727 } |
| 1728 this.requestDocument(onDocumentAvailable.bind(this)); |
| 1729 } |
| 1730 |
| 1731 /** |
| 1732 * @return {boolean} |
| 1733 */ |
| 1734 inspectModeEnabled() { |
| 1735 return this._inspectModeEnabled; |
| 1736 } |
| 1737 |
| 1738 /** |
| 1739 * @param {string=} mode |
| 1740 * @return {!DOMAgent.HighlightConfig} |
| 1741 */ |
| 1742 _buildHighlightConfig(mode) { |
| 1743 mode = mode || 'all'; |
| 1744 var showRulers = WebInspector.moduleSetting('showMetricsRulers').get(); |
| 1745 var highlightConfig = {showInfo: mode === 'all', showRulers: showRulers, sho
wExtensionLines: showRulers}; |
| 1746 if (mode === 'all' || mode === 'content') |
| 1747 highlightConfig.contentColor = WebInspector.Color.PageHighlight.Content.to
ProtocolRGBA(); |
| 1748 |
| 1749 if (mode === 'all' || mode === 'padding') |
| 1750 highlightConfig.paddingColor = WebInspector.Color.PageHighlight.Padding.to
ProtocolRGBA(); |
| 1751 |
| 1752 if (mode === 'all' || mode === 'border') |
| 1753 highlightConfig.borderColor = WebInspector.Color.PageHighlight.Border.toPr
otocolRGBA(); |
| 1754 |
| 1755 if (mode === 'all' || mode === 'margin') |
| 1756 highlightConfig.marginColor = WebInspector.Color.PageHighlight.Margin.toPr
otocolRGBA(); |
| 1757 |
| 1758 if (mode === 'all') { |
| 1759 highlightConfig.eventTargetColor = WebInspector.Color.PageHighlight.EventT
arget.toProtocolRGBA(); |
| 1760 highlightConfig.shapeColor = WebInspector.Color.PageHighlight.Shape.toProt
ocolRGBA(); |
| 1761 highlightConfig.shapeMarginColor = WebInspector.Color.PageHighlight.ShapeM
argin.toProtocolRGBA(); |
| 1762 highlightConfig.displayAsMaterial = Runtime.experiments.isEnabled('inspect
Tooltip'); |
| 1763 } |
| 1764 return highlightConfig; |
| 1765 } |
| 1766 |
| 1767 /** |
| 1768 * @param {!WebInspector.DOMNode} node |
| 1769 * @param {function(?Protocol.Error, ...)=} callback |
| 1770 * @return {function(...)} |
| 1771 * @template T |
| 1772 */ |
| 1773 _markRevision(node, callback) { |
| 1774 /** |
| 1775 * @param {?Protocol.Error} error |
| 1776 * @this {WebInspector.DOMModel} |
| 1777 */ |
| 1778 function wrapperFunction(error) { |
| 1779 if (!error) |
| 1780 this.markUndoableState(); |
| 1781 |
| 1782 if (callback) |
| 1783 callback.apply(this, arguments); |
| 1784 } |
| 1785 return wrapperFunction.bind(this); |
| 1786 } |
| 1787 |
| 1788 markUndoableState() { |
| 1789 this._agent.markUndoableState(); |
| 1790 } |
| 1791 |
| 1792 /** |
| 1793 * @param {function(?Protocol.Error)=} callback |
| 1794 */ |
| 1795 undo(callback) { |
| 1796 /** |
| 1797 * @param {?Protocol.Error} error |
| 1798 * @this {WebInspector.DOMModel} |
| 1799 */ |
| 1800 function mycallback(error) { |
| 1801 this.dispatchEventToListeners(WebInspector.DOMModel.Events.UndoRedoComplet
ed); |
| 1802 callback(error); |
| 1803 } |
| 1804 |
| 1805 this.dispatchEventToListeners(WebInspector.DOMModel.Events.UndoRedoRequested
); |
| 1806 this._agent.undo(callback); |
| 1807 } |
| 1808 |
| 1809 /** |
| 1810 * @param {function(?Protocol.Error)=} callback |
| 1811 */ |
| 1812 redo(callback) { |
| 1813 /** |
| 1814 * @param {?Protocol.Error} error |
| 1815 * @this {WebInspector.DOMModel} |
| 1816 */ |
| 1817 function mycallback(error) { |
| 1818 this.dispatchEventToListeners(WebInspector.DOMModel.Events.UndoRedoComplet
ed); |
| 1819 callback(error); |
| 1820 } |
| 1821 |
| 1822 this.dispatchEventToListeners(WebInspector.DOMModel.Events.UndoRedoRequested
); |
| 1823 this._agent.redo(callback); |
| 1824 } |
| 1825 |
| 1826 /** |
| 1827 * @param {?WebInspector.DOMNodeHighlighter} highlighter |
| 1828 */ |
| 1829 setHighlighter(highlighter) { |
| 1830 this._highlighter = highlighter || this._defaultHighlighter; |
| 1831 } |
| 1832 |
| 1833 /** |
| 1834 * @param {number} x |
| 1835 * @param {number} y |
| 1836 * @param {function(?WebInspector.DOMNode)} callback |
| 1837 */ |
| 1838 nodeForLocation(x, y, callback) { |
| 1839 this._agent.getNodeForLocation(x, y, mycallback.bind(this)); |
| 1840 |
| 1841 /** |
| 1842 * @param {?Protocol.Error} error |
| 1843 * @param {number} nodeId |
| 1844 * @this {WebInspector.DOMModel} |
| 1845 */ |
| 1846 function mycallback(error, nodeId) { |
| 1847 if (error) { |
| 1848 callback(null); |
| 1849 return; |
| 1850 } |
| 1851 callback(this.nodeForId(nodeId)); |
| 1852 } |
| 1853 } |
| 1854 |
| 1855 /** |
| 1856 * @param {!WebInspector.RemoteObject} object |
| 1857 * @param {function(?WebInspector.DOMNode)} callback |
| 1858 */ |
| 1859 pushObjectAsNodeToFrontend(object, callback) { |
| 1860 if (object.isNode()) |
| 1861 this.pushNodeToFrontend(object.objectId, callback); |
| 1862 else |
| 1863 callback(null); |
| 1864 } |
| 1865 |
| 1866 /** |
| 1867 * @override |
| 1868 * @return {!Promise} |
| 1869 */ |
| 1870 suspendModel() { |
| 1871 return new Promise(promiseBody.bind(this)); |
| 1872 |
| 1873 /** |
| 1874 * @param {function()} fulfill |
| 1875 * @this {WebInspector.DOMModel} |
| 1876 */ |
| 1877 function promiseBody(fulfill) { |
| 1878 this._agent.disable(callback.bind(this)); |
| 1879 |
| 1880 /** |
| 1881 * @this {WebInspector.DOMModel} |
| 1882 */ |
| 1883 function callback() { |
| 1884 this._setDocument(null); |
| 1885 fulfill(); |
| 1886 } |
| 1887 } |
| 1888 } |
| 1889 |
| 1890 /** |
| 1891 * @override |
| 1892 * @return {!Promise} |
| 1893 */ |
| 1894 resumeModel() { |
| 1895 return new Promise(promiseBody.bind(this)); |
| 1896 |
| 1897 /** |
| 1898 * @param {function()} fulfill |
| 1899 * @this {WebInspector.DOMModel} |
| 1900 */ |
| 1901 function promiseBody(fulfill) { |
| 1902 this._agent.enable(fulfill); |
| 1903 } |
| 1904 } |
| 1905 |
| 1906 /** |
| 1907 * @param {!DOMAgent.NodeId} nodeId |
| 1908 */ |
| 1909 nodeHighlightRequested(nodeId) { |
| 1910 var node = this.nodeForId(nodeId); |
| 1911 if (!node) |
| 1912 return; |
| 1913 |
| 1914 this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeHighlightedIn
Overlay, node); |
| 1915 } |
| 1134 }; | 1916 }; |
| 1135 | 1917 |
| 1136 /** @enum {symbol} */ | 1918 /** @enum {symbol} */ |
| 1137 WebInspector.DOMModel.Events = { | 1919 WebInspector.DOMModel.Events = { |
| 1138 AttrModified: Symbol("AttrModified"), | 1920 AttrModified: Symbol('AttrModified'), |
| 1139 AttrRemoved: Symbol("AttrRemoved"), | 1921 AttrRemoved: Symbol('AttrRemoved'), |
| 1140 CharacterDataModified: Symbol("CharacterDataModified"), | 1922 CharacterDataModified: Symbol('CharacterDataModified'), |
| 1141 DOMMutated: Symbol("DOMMutated"), | 1923 DOMMutated: Symbol('DOMMutated'), |
| 1142 NodeInserted: Symbol("NodeInserted"), | 1924 NodeInserted: Symbol('NodeInserted'), |
| 1143 NodeInspected: Symbol("NodeInspected"), | 1925 NodeInspected: Symbol('NodeInspected'), |
| 1144 NodeHighlightedInOverlay: Symbol("NodeHighlightedInOverlay"), | 1926 NodeHighlightedInOverlay: Symbol('NodeHighlightedInOverlay'), |
| 1145 NodeRemoved: Symbol("NodeRemoved"), | 1927 NodeRemoved: Symbol('NodeRemoved'), |
| 1146 DocumentUpdated: Symbol("DocumentUpdated"), | 1928 DocumentUpdated: Symbol('DocumentUpdated'), |
| 1147 ChildNodeCountUpdated: Symbol("ChildNodeCountUpdated"), | 1929 ChildNodeCountUpdated: Symbol('ChildNodeCountUpdated'), |
| 1148 UndoRedoRequested: Symbol("UndoRedoRequested"), | 1930 UndoRedoRequested: Symbol('UndoRedoRequested'), |
| 1149 UndoRedoCompleted: Symbol("UndoRedoCompleted"), | 1931 UndoRedoCompleted: Symbol('UndoRedoCompleted'), |
| 1150 DistributedNodesChanged: Symbol("DistributedNodesChanged"), | 1932 DistributedNodesChanged: Symbol('DistributedNodesChanged'), |
| 1151 ModelSuspended: Symbol("ModelSuspended"), | 1933 ModelSuspended: Symbol('ModelSuspended'), |
| 1152 InspectModeWillBeToggled: Symbol("InspectModeWillBeToggled"), | 1934 InspectModeWillBeToggled: Symbol('InspectModeWillBeToggled'), |
| 1153 MarkersChanged: Symbol("MarkersChanged") | 1935 MarkersChanged: Symbol('MarkersChanged') |
| 1154 }; | 1936 }; |
| 1155 | 1937 |
| 1938 |
| 1156 /** | 1939 /** |
| 1157 * @param {!WebInspector.RemoteObject} object | 1940 * @implements {DOMAgent.Dispatcher} |
| 1941 * @unrestricted |
| 1158 */ | 1942 */ |
| 1159 WebInspector.DOMModel.highlightObjectAsDOMNode = function(object) | 1943 WebInspector.DOMDispatcher = class { |
| 1160 { | 1944 /** |
| 1161 var domModel = WebInspector.DOMModel.fromTarget(object.target()); | 1945 * @param {!WebInspector.DOMModel} domModel |
| 1162 if (domModel) | 1946 */ |
| 1163 domModel.highlightDOMNode(undefined, undefined, undefined, object.object
Id); | 1947 constructor(domModel) { |
| 1164 }; | |
| 1165 | |
| 1166 /** | |
| 1167 * @return {!Array<!WebInspector.DOMModel>} | |
| 1168 */ | |
| 1169 WebInspector.DOMModel.instances = function() | |
| 1170 { | |
| 1171 var result = []; | |
| 1172 for (var target of WebInspector.targetManager.targets()) { | |
| 1173 var domModel = WebInspector.DOMModel.fromTarget(target); | |
| 1174 if (domModel) | |
| 1175 result.push(domModel); | |
| 1176 } | |
| 1177 return result; | |
| 1178 }; | |
| 1179 | |
| 1180 WebInspector.DOMModel.hideDOMNodeHighlight = function() | |
| 1181 { | |
| 1182 for (var domModel of WebInspector.DOMModel.instances()) | |
| 1183 domModel.highlightDOMNode(0); | |
| 1184 }; | |
| 1185 | |
| 1186 WebInspector.DOMModel.muteHighlight = function() | |
| 1187 { | |
| 1188 WebInspector.DOMModel.hideDOMNodeHighlight(); | |
| 1189 WebInspector.DOMModel._highlightDisabled = true; | |
| 1190 }; | |
| 1191 | |
| 1192 WebInspector.DOMModel.unmuteHighlight = function() | |
| 1193 { | |
| 1194 WebInspector.DOMModel._highlightDisabled = false; | |
| 1195 }; | |
| 1196 | |
| 1197 WebInspector.DOMModel.cancelSearch = function() | |
| 1198 { | |
| 1199 for (var domModel of WebInspector.DOMModel.instances()) | |
| 1200 domModel._cancelSearch(); | |
| 1201 }; | |
| 1202 | |
| 1203 WebInspector.DOMModel.prototype = { | |
| 1204 /** | |
| 1205 * @param {!WebInspector.DOMNode} node | |
| 1206 */ | |
| 1207 _scheduleMutationEvent: function(node) | |
| 1208 { | |
| 1209 if (!this.hasEventListeners(WebInspector.DOMModel.Events.DOMMutated)) | |
| 1210 return; | |
| 1211 | |
| 1212 this._lastMutationId = (this._lastMutationId || 0) + 1; | |
| 1213 Promise.resolve().then(callObserve.bind(this, node, this._lastMutationId
)); | |
| 1214 | |
| 1215 /** | |
| 1216 * @this {WebInspector.DOMModel} | |
| 1217 * @param {!WebInspector.DOMNode} node | |
| 1218 * @param {number} mutationId | |
| 1219 */ | |
| 1220 function callObserve(node, mutationId) | |
| 1221 { | |
| 1222 if (!this.hasEventListeners(WebInspector.DOMModel.Events.DOMMutated)
|| this._lastMutationId !== mutationId) | |
| 1223 return; | |
| 1224 | |
| 1225 this.dispatchEventToListeners(WebInspector.DOMModel.Events.DOMMutate
d, node); | |
| 1226 } | |
| 1227 }, | |
| 1228 | |
| 1229 /** | |
| 1230 * @param {function(!WebInspector.DOMDocument)=} callback | |
| 1231 */ | |
| 1232 requestDocument: function(callback) | |
| 1233 { | |
| 1234 if (this._document) { | |
| 1235 if (callback) | |
| 1236 callback(this._document); | |
| 1237 return; | |
| 1238 } | |
| 1239 | |
| 1240 if (this._pendingDocumentRequestCallbacks) { | |
| 1241 this._pendingDocumentRequestCallbacks.push(callback); | |
| 1242 return; | |
| 1243 } | |
| 1244 | |
| 1245 this._pendingDocumentRequestCallbacks = [callback]; | |
| 1246 | |
| 1247 /** | |
| 1248 * @this {WebInspector.DOMModel} | |
| 1249 * @param {?Protocol.Error} error | |
| 1250 * @param {!DOMAgent.Node} root | |
| 1251 */ | |
| 1252 function onDocumentAvailable(error, root) | |
| 1253 { | |
| 1254 if (!error) | |
| 1255 this._setDocument(root); | |
| 1256 | |
| 1257 for (var i = 0; i < this._pendingDocumentRequestCallbacks.length; ++
i) { | |
| 1258 var callback = this._pendingDocumentRequestCallbacks[i]; | |
| 1259 if (callback) | |
| 1260 callback(this._document); | |
| 1261 } | |
| 1262 delete this._pendingDocumentRequestCallbacks; | |
| 1263 } | |
| 1264 | |
| 1265 this._agent.getDocument(undefined, undefined, onDocumentAvailable.bind(t
his)); | |
| 1266 }, | |
| 1267 | |
| 1268 /** | |
| 1269 * @return {?WebInspector.DOMDocument} | |
| 1270 */ | |
| 1271 existingDocument: function() | |
| 1272 { | |
| 1273 return this._document; | |
| 1274 }, | |
| 1275 | |
| 1276 /** | |
| 1277 * @param {!RuntimeAgent.RemoteObjectId} objectId | |
| 1278 * @param {function(?WebInspector.DOMNode)=} callback | |
| 1279 */ | |
| 1280 pushNodeToFrontend: function(objectId, callback) | |
| 1281 { | |
| 1282 /** | |
| 1283 * @param {?DOMAgent.NodeId} nodeId | |
| 1284 * @this {!WebInspector.DOMModel} | |
| 1285 */ | |
| 1286 function mycallback(nodeId) | |
| 1287 { | |
| 1288 callback(nodeId ? this.nodeForId(nodeId) : null); | |
| 1289 } | |
| 1290 this._dispatchWhenDocumentAvailable(this._agent.requestNode.bind(this._a
gent, objectId), mycallback.bind(this)); | |
| 1291 }, | |
| 1292 | |
| 1293 /** | |
| 1294 * @param {string} path | |
| 1295 * @param {function(?number)=} callback | |
| 1296 */ | |
| 1297 pushNodeByPathToFrontend: function(path, callback) | |
| 1298 { | |
| 1299 this._dispatchWhenDocumentAvailable(this._agent.pushNodeByPathToFrontend
.bind(this._agent, path), callback); | |
| 1300 }, | |
| 1301 | |
| 1302 /** | |
| 1303 * @param {!Set<number>} backendNodeIds | |
| 1304 * @param {function(?Map<number, ?WebInspector.DOMNode>)} callback | |
| 1305 */ | |
| 1306 pushNodesByBackendIdsToFrontend: function(backendNodeIds, callback) | |
| 1307 { | |
| 1308 var backendNodeIdsArray = backendNodeIds.valuesArray(); | |
| 1309 /** | |
| 1310 * @param {?Array<!DOMAgent.NodeId>} nodeIds | |
| 1311 * @this {!WebInspector.DOMModel} | |
| 1312 */ | |
| 1313 function mycallback(nodeIds) | |
| 1314 { | |
| 1315 if (!nodeIds) { | |
| 1316 callback(null); | |
| 1317 return; | |
| 1318 } | |
| 1319 /** @type {!Map<number, ?WebInspector.DOMNode>} */ | |
| 1320 var map = new Map(); | |
| 1321 for (var i = 0; i < nodeIds.length; ++i) { | |
| 1322 if (nodeIds[i]) | |
| 1323 map.set(backendNodeIdsArray[i], this.nodeForId(nodeIds[i])); | |
| 1324 } | |
| 1325 callback(map); | |
| 1326 } | |
| 1327 this._dispatchWhenDocumentAvailable(this._agent.pushNodesByBackendIdsToF
rontend.bind(this._agent, backendNodeIdsArray), mycallback.bind(this)); | |
| 1328 }, | |
| 1329 | |
| 1330 /** | |
| 1331 * @param {function(!T)=} callback | |
| 1332 * @return {function(?Protocol.Error, !T=)|undefined} | |
| 1333 * @template T | |
| 1334 */ | |
| 1335 _wrapClientCallback: function(callback) | |
| 1336 { | |
| 1337 if (!callback) | |
| 1338 return; | |
| 1339 /** | |
| 1340 * @param {?Protocol.Error} error | |
| 1341 * @param {!T=} result | |
| 1342 * @template T | |
| 1343 */ | |
| 1344 var wrapper = function(error, result) | |
| 1345 { | |
| 1346 // Caller is responsible for handling the actual error. | |
| 1347 callback(error ? null : result); | |
| 1348 }; | |
| 1349 return wrapper; | |
| 1350 }, | |
| 1351 | |
| 1352 /** | |
| 1353 * @param {function(function(?Protocol.Error, !T=)=)} func | |
| 1354 * @param {function(!T)=} callback | |
| 1355 * @template T | |
| 1356 */ | |
| 1357 _dispatchWhenDocumentAvailable: function(func, callback) | |
| 1358 { | |
| 1359 var callbackWrapper = this._wrapClientCallback(callback); | |
| 1360 | |
| 1361 /** | |
| 1362 * @this {WebInspector.DOMModel} | |
| 1363 */ | |
| 1364 function onDocumentAvailable() | |
| 1365 { | |
| 1366 if (this._document) | |
| 1367 func(callbackWrapper); | |
| 1368 else { | |
| 1369 if (callbackWrapper) | |
| 1370 callbackWrapper("No document"); | |
| 1371 } | |
| 1372 } | |
| 1373 this.requestDocument(onDocumentAvailable.bind(this)); | |
| 1374 }, | |
| 1375 | |
| 1376 /** | |
| 1377 * @param {!DOMAgent.NodeId} nodeId | |
| 1378 * @param {string} name | |
| 1379 * @param {string} value | |
| 1380 */ | |
| 1381 _attributeModified: function(nodeId, name, value) | |
| 1382 { | |
| 1383 var node = this._idToDOMNode[nodeId]; | |
| 1384 if (!node) | |
| 1385 return; | |
| 1386 | |
| 1387 node._setAttribute(name, value); | |
| 1388 this.dispatchEventToListeners(WebInspector.DOMModel.Events.AttrModified,
{ node: node, name: name }); | |
| 1389 this._scheduleMutationEvent(node); | |
| 1390 }, | |
| 1391 | |
| 1392 /** | |
| 1393 * @param {!DOMAgent.NodeId} nodeId | |
| 1394 * @param {string} name | |
| 1395 */ | |
| 1396 _attributeRemoved: function(nodeId, name) | |
| 1397 { | |
| 1398 var node = this._idToDOMNode[nodeId]; | |
| 1399 if (!node) | |
| 1400 return; | |
| 1401 node._removeAttribute(name); | |
| 1402 this.dispatchEventToListeners(WebInspector.DOMModel.Events.AttrRemoved,
{ node: node, name: name }); | |
| 1403 this._scheduleMutationEvent(node); | |
| 1404 }, | |
| 1405 | |
| 1406 /** | |
| 1407 * @param {!Array.<!DOMAgent.NodeId>} nodeIds | |
| 1408 */ | |
| 1409 _inlineStyleInvalidated: function(nodeIds) | |
| 1410 { | |
| 1411 for (var i = 0; i < nodeIds.length; ++i) | |
| 1412 this._attributeLoadNodeIds[nodeIds[i]] = true; | |
| 1413 if ("_loadNodeAttributesTimeout" in this) | |
| 1414 return; | |
| 1415 this._loadNodeAttributesTimeout = setTimeout(this._loadNodeAttributes.bi
nd(this), 20); | |
| 1416 }, | |
| 1417 | |
| 1418 _loadNodeAttributes: function() | |
| 1419 { | |
| 1420 /** | |
| 1421 * @this {WebInspector.DOMModel} | |
| 1422 * @param {!DOMAgent.NodeId} nodeId | |
| 1423 * @param {?Protocol.Error} error | |
| 1424 * @param {!Array.<string>} attributes | |
| 1425 */ | |
| 1426 function callback(nodeId, error, attributes) | |
| 1427 { | |
| 1428 if (error) { | |
| 1429 // We are calling _loadNodeAttributes asynchronously, it is ok i
f node is not found. | |
| 1430 return; | |
| 1431 } | |
| 1432 var node = this._idToDOMNode[nodeId]; | |
| 1433 if (node) { | |
| 1434 if (node._setAttributesPayload(attributes)) { | |
| 1435 this.dispatchEventToListeners(WebInspector.DOMModel.Events.A
ttrModified, { node: node, name: "style" }); | |
| 1436 this._scheduleMutationEvent(node); | |
| 1437 } | |
| 1438 } | |
| 1439 } | |
| 1440 | |
| 1441 delete this._loadNodeAttributesTimeout; | |
| 1442 | |
| 1443 for (var nodeId in this._attributeLoadNodeIds) { | |
| 1444 var nodeIdAsNumber = parseInt(nodeId, 10); | |
| 1445 this._agent.getAttributes(nodeIdAsNumber, callback.bind(this, nodeId
AsNumber)); | |
| 1446 } | |
| 1447 this._attributeLoadNodeIds = {}; | |
| 1448 }, | |
| 1449 | |
| 1450 /** | |
| 1451 * @param {!DOMAgent.NodeId} nodeId | |
| 1452 * @param {string} newValue | |
| 1453 */ | |
| 1454 _characterDataModified: function(nodeId, newValue) | |
| 1455 { | |
| 1456 var node = this._idToDOMNode[nodeId]; | |
| 1457 node._nodeValue = newValue; | |
| 1458 this.dispatchEventToListeners(WebInspector.DOMModel.Events.CharacterData
Modified, node); | |
| 1459 this._scheduleMutationEvent(node); | |
| 1460 }, | |
| 1461 | |
| 1462 /** | |
| 1463 * @param {!DOMAgent.NodeId} nodeId | |
| 1464 * @return {?WebInspector.DOMNode} | |
| 1465 */ | |
| 1466 nodeForId: function(nodeId) | |
| 1467 { | |
| 1468 return this._idToDOMNode[nodeId] || null; | |
| 1469 }, | |
| 1470 | |
| 1471 _documentUpdated: function() | |
| 1472 { | |
| 1473 this._setDocument(null); | |
| 1474 }, | |
| 1475 | |
| 1476 /** | |
| 1477 * @param {?DOMAgent.Node} payload | |
| 1478 */ | |
| 1479 _setDocument: function(payload) | |
| 1480 { | |
| 1481 this._idToDOMNode = {}; | |
| 1482 if (payload && "nodeId" in payload) | |
| 1483 this._document = new WebInspector.DOMDocument(this, payload); | |
| 1484 else | |
| 1485 this._document = null; | |
| 1486 this.dispatchEventToListeners(WebInspector.DOMModel.Events.DocumentUpdat
ed, this._document); | |
| 1487 }, | |
| 1488 | |
| 1489 /** | |
| 1490 * @param {!DOMAgent.Node} payload | |
| 1491 */ | |
| 1492 _setDetachedRoot: function(payload) | |
| 1493 { | |
| 1494 if (payload.nodeName === "#document") | |
| 1495 new WebInspector.DOMDocument(this, payload); | |
| 1496 else | |
| 1497 WebInspector.DOMNode.create(this, null, false, payload); | |
| 1498 }, | |
| 1499 | |
| 1500 /** | |
| 1501 * @param {!DOMAgent.NodeId} parentId | |
| 1502 * @param {!Array.<!DOMAgent.Node>} payloads | |
| 1503 */ | |
| 1504 _setChildNodes: function(parentId, payloads) | |
| 1505 { | |
| 1506 if (!parentId && payloads.length) { | |
| 1507 this._setDetachedRoot(payloads[0]); | |
| 1508 return; | |
| 1509 } | |
| 1510 | |
| 1511 var parent = this._idToDOMNode[parentId]; | |
| 1512 parent._setChildrenPayload(payloads); | |
| 1513 }, | |
| 1514 | |
| 1515 /** | |
| 1516 * @param {!DOMAgent.NodeId} nodeId | |
| 1517 * @param {number} newValue | |
| 1518 */ | |
| 1519 _childNodeCountUpdated: function(nodeId, newValue) | |
| 1520 { | |
| 1521 var node = this._idToDOMNode[nodeId]; | |
| 1522 node._childNodeCount = newValue; | |
| 1523 this.dispatchEventToListeners(WebInspector.DOMModel.Events.ChildNodeCoun
tUpdated, node); | |
| 1524 this._scheduleMutationEvent(node); | |
| 1525 }, | |
| 1526 | |
| 1527 /** | |
| 1528 * @param {!DOMAgent.NodeId} parentId | |
| 1529 * @param {!DOMAgent.NodeId} prevId | |
| 1530 * @param {!DOMAgent.Node} payload | |
| 1531 */ | |
| 1532 _childNodeInserted: function(parentId, prevId, payload) | |
| 1533 { | |
| 1534 var parent = this._idToDOMNode[parentId]; | |
| 1535 var prev = this._idToDOMNode[prevId]; | |
| 1536 var node = parent._insertChild(prev, payload); | |
| 1537 this._idToDOMNode[node.id] = node; | |
| 1538 this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeInserted,
node); | |
| 1539 this._scheduleMutationEvent(node); | |
| 1540 }, | |
| 1541 | |
| 1542 /** | |
| 1543 * @param {!DOMAgent.NodeId} parentId | |
| 1544 * @param {!DOMAgent.NodeId} nodeId | |
| 1545 */ | |
| 1546 _childNodeRemoved: function(parentId, nodeId) | |
| 1547 { | |
| 1548 var parent = this._idToDOMNode[parentId]; | |
| 1549 var node = this._idToDOMNode[nodeId]; | |
| 1550 parent._removeChild(node); | |
| 1551 this._unbind(node); | |
| 1552 this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeRemoved,
{node: node, parent: parent}); | |
| 1553 this._scheduleMutationEvent(node); | |
| 1554 }, | |
| 1555 | |
| 1556 /** | |
| 1557 * @param {!DOMAgent.NodeId} hostId | |
| 1558 * @param {!DOMAgent.Node} root | |
| 1559 */ | |
| 1560 _shadowRootPushed: function(hostId, root) | |
| 1561 { | |
| 1562 var host = this._idToDOMNode[hostId]; | |
| 1563 if (!host) | |
| 1564 return; | |
| 1565 var node = WebInspector.DOMNode.create(this, host.ownerDocument, true, r
oot); | |
| 1566 node.parentNode = host; | |
| 1567 this._idToDOMNode[node.id] = node; | |
| 1568 host._shadowRoots.unshift(node); | |
| 1569 this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeInserted,
node); | |
| 1570 this._scheduleMutationEvent(node); | |
| 1571 }, | |
| 1572 | |
| 1573 /** | |
| 1574 * @param {!DOMAgent.NodeId} hostId | |
| 1575 * @param {!DOMAgent.NodeId} rootId | |
| 1576 */ | |
| 1577 _shadowRootPopped: function(hostId, rootId) | |
| 1578 { | |
| 1579 var host = this._idToDOMNode[hostId]; | |
| 1580 if (!host) | |
| 1581 return; | |
| 1582 var root = this._idToDOMNode[rootId]; | |
| 1583 if (!root) | |
| 1584 return; | |
| 1585 host._removeChild(root); | |
| 1586 this._unbind(root); | |
| 1587 this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeRemoved,
{node: root, parent: host}); | |
| 1588 this._scheduleMutationEvent(root); | |
| 1589 }, | |
| 1590 | |
| 1591 /** | |
| 1592 * @param {!DOMAgent.NodeId} parentId | |
| 1593 * @param {!DOMAgent.Node} pseudoElement | |
| 1594 */ | |
| 1595 _pseudoElementAdded: function(parentId, pseudoElement) | |
| 1596 { | |
| 1597 var parent = this._idToDOMNode[parentId]; | |
| 1598 if (!parent) | |
| 1599 return; | |
| 1600 var node = WebInspector.DOMNode.create(this, parent.ownerDocument, false
, pseudoElement); | |
| 1601 node.parentNode = parent; | |
| 1602 this._idToDOMNode[node.id] = node; | |
| 1603 console.assert(!parent._pseudoElements.get(node.pseudoType())); | |
| 1604 parent._pseudoElements.set(node.pseudoType(), node); | |
| 1605 this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeInserted,
node); | |
| 1606 this._scheduleMutationEvent(node); | |
| 1607 }, | |
| 1608 | |
| 1609 /** | |
| 1610 * @param {!DOMAgent.NodeId} parentId | |
| 1611 * @param {!DOMAgent.NodeId} pseudoElementId | |
| 1612 */ | |
| 1613 _pseudoElementRemoved: function(parentId, pseudoElementId) | |
| 1614 { | |
| 1615 var parent = this._idToDOMNode[parentId]; | |
| 1616 if (!parent) | |
| 1617 return; | |
| 1618 var pseudoElement = this._idToDOMNode[pseudoElementId]; | |
| 1619 if (!pseudoElement) | |
| 1620 return; | |
| 1621 parent._removeChild(pseudoElement); | |
| 1622 this._unbind(pseudoElement); | |
| 1623 this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeRemoved,
{node: pseudoElement, parent: parent}); | |
| 1624 this._scheduleMutationEvent(pseudoElement); | |
| 1625 }, | |
| 1626 | |
| 1627 /** | |
| 1628 * @param {!DOMAgent.NodeId} insertionPointId | |
| 1629 * @param {!Array.<!DOMAgent.BackendNode>} distributedNodes | |
| 1630 */ | |
| 1631 _distributedNodesUpdated: function(insertionPointId, distributedNodes) | |
| 1632 { | |
| 1633 var insertionPoint = this._idToDOMNode[insertionPointId]; | |
| 1634 if (!insertionPoint) | |
| 1635 return; | |
| 1636 insertionPoint._setDistributedNodePayloads(distributedNodes); | |
| 1637 this.dispatchEventToListeners(WebInspector.DOMModel.Events.DistributedNo
desChanged, insertionPoint); | |
| 1638 this._scheduleMutationEvent(insertionPoint); | |
| 1639 }, | |
| 1640 | |
| 1641 /** | |
| 1642 * @param {!WebInspector.DOMNode} node | |
| 1643 */ | |
| 1644 _unbind: function(node) | |
| 1645 { | |
| 1646 delete this._idToDOMNode[node.id]; | |
| 1647 for (var i = 0; node._children && i < node._children.length; ++i) | |
| 1648 this._unbind(node._children[i]); | |
| 1649 for (var i = 0; i < node._shadowRoots.length; ++i) | |
| 1650 this._unbind(node._shadowRoots[i]); | |
| 1651 var pseudoElements = node.pseudoElements(); | |
| 1652 for (var value of pseudoElements.values()) | |
| 1653 this._unbind(value); | |
| 1654 if (node._templateContent) | |
| 1655 this._unbind(node._templateContent); | |
| 1656 }, | |
| 1657 | |
| 1658 /** | |
| 1659 * @param {!DOMAgent.BackendNodeId} backendNodeId | |
| 1660 */ | |
| 1661 _inspectNodeRequested: function(backendNodeId) | |
| 1662 { | |
| 1663 var deferredNode = new WebInspector.DeferredDOMNode(this.target(), backe
ndNodeId); | |
| 1664 this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeInspected
, deferredNode); | |
| 1665 }, | |
| 1666 | |
| 1667 /** | |
| 1668 * @param {string} query | |
| 1669 * @param {boolean} includeUserAgentShadowDOM | |
| 1670 * @param {function(number)} searchCallback | |
| 1671 */ | |
| 1672 performSearch: function(query, includeUserAgentShadowDOM, searchCallback) | |
| 1673 { | |
| 1674 WebInspector.DOMModel.cancelSearch(); | |
| 1675 | |
| 1676 /** | |
| 1677 * @param {?Protocol.Error} error | |
| 1678 * @param {string} searchId | |
| 1679 * @param {number} resultsCount | |
| 1680 * @this {WebInspector.DOMModel} | |
| 1681 */ | |
| 1682 function callback(error, searchId, resultsCount) | |
| 1683 { | |
| 1684 this._searchId = searchId; | |
| 1685 searchCallback(resultsCount); | |
| 1686 } | |
| 1687 this._agent.performSearch(query, includeUserAgentShadowDOM, callback.bin
d(this)); | |
| 1688 }, | |
| 1689 | |
| 1690 /** | |
| 1691 * @param {string} query | |
| 1692 * @param {boolean} includeUserAgentShadowDOM | |
| 1693 * @return {!Promise.<number>} | |
| 1694 */ | |
| 1695 performSearchPromise: function(query, includeUserAgentShadowDOM) | |
| 1696 { | |
| 1697 return new Promise(performSearch.bind(this)); | |
| 1698 | |
| 1699 /** | |
| 1700 * @param {function(number)} resolve | |
| 1701 * @this {WebInspector.DOMModel} | |
| 1702 */ | |
| 1703 function performSearch(resolve) | |
| 1704 { | |
| 1705 this._agent.performSearch(query, includeUserAgentShadowDOM, callback
.bind(this)); | |
| 1706 | |
| 1707 /** | |
| 1708 * @param {?Protocol.Error} error | |
| 1709 * @param {string} searchId | |
| 1710 * @param {number} resultsCount | |
| 1711 * @this {WebInspector.DOMModel} | |
| 1712 */ | |
| 1713 function callback(error, searchId, resultsCount) | |
| 1714 { | |
| 1715 if (!error) | |
| 1716 this._searchId = searchId; | |
| 1717 resolve(error ? 0 : resultsCount); | |
| 1718 } | |
| 1719 } | |
| 1720 }, | |
| 1721 | |
| 1722 /** | |
| 1723 * @param {number} index | |
| 1724 * @param {?function(?WebInspector.DOMNode)} callback | |
| 1725 */ | |
| 1726 searchResult: function(index, callback) | |
| 1727 { | |
| 1728 if (this._searchId) | |
| 1729 this._agent.getSearchResults(this._searchId, index, index + 1, searc
hResultsCallback.bind(this)); | |
| 1730 else | |
| 1731 callback(null); | |
| 1732 | |
| 1733 /** | |
| 1734 * @param {?Protocol.Error} error | |
| 1735 * @param {!Array.<number>} nodeIds | |
| 1736 * @this {WebInspector.DOMModel} | |
| 1737 */ | |
| 1738 function searchResultsCallback(error, nodeIds) | |
| 1739 { | |
| 1740 if (error) { | |
| 1741 console.error(error); | |
| 1742 callback(null); | |
| 1743 return; | |
| 1744 } | |
| 1745 if (nodeIds.length !== 1) | |
| 1746 return; | |
| 1747 | |
| 1748 callback(this.nodeForId(nodeIds[0])); | |
| 1749 } | |
| 1750 }, | |
| 1751 | |
| 1752 _cancelSearch: function() | |
| 1753 { | |
| 1754 if (this._searchId) { | |
| 1755 this._agent.discardSearchResults(this._searchId); | |
| 1756 delete this._searchId; | |
| 1757 } | |
| 1758 }, | |
| 1759 | |
| 1760 /** | |
| 1761 * @param {!DOMAgent.NodeId} nodeId | |
| 1762 * @return {!Promise<!Array<string>>} | |
| 1763 */ | |
| 1764 classNamesPromise: function(nodeId) | |
| 1765 { | |
| 1766 return new Promise(promiseBody.bind(this)); | |
| 1767 | |
| 1768 /** | |
| 1769 * @param {function(!Array<string>)} fulfill | |
| 1770 * @this {WebInspector.DOMModel} | |
| 1771 */ | |
| 1772 function promiseBody(fulfill) | |
| 1773 { | |
| 1774 this._agent.collectClassNamesFromSubtree(nodeId, classNamesCallback)
; | |
| 1775 | |
| 1776 /** | |
| 1777 * @param {?string} error | |
| 1778 * @param {?Array<string>} classNames | |
| 1779 */ | |
| 1780 function classNamesCallback(error, classNames) | |
| 1781 { | |
| 1782 if (!error && classNames) | |
| 1783 fulfill(classNames); | |
| 1784 else | |
| 1785 fulfill([]); | |
| 1786 } | |
| 1787 } | |
| 1788 }, | |
| 1789 | |
| 1790 /** | |
| 1791 * @param {!DOMAgent.NodeId} nodeId | |
| 1792 * @param {string} selectors | |
| 1793 * @param {function(?DOMAgent.NodeId)=} callback | |
| 1794 */ | |
| 1795 querySelector: function(nodeId, selectors, callback) | |
| 1796 { | |
| 1797 this._agent.querySelector(nodeId, selectors, this._wrapClientCallback(ca
llback)); | |
| 1798 }, | |
| 1799 | |
| 1800 /** | |
| 1801 * @param {!DOMAgent.NodeId} nodeId | |
| 1802 * @param {string} selectors | |
| 1803 * @param {function(!Array.<!DOMAgent.NodeId>=)=} callback | |
| 1804 */ | |
| 1805 querySelectorAll: function(nodeId, selectors, callback) | |
| 1806 { | |
| 1807 this._agent.querySelectorAll(nodeId, selectors, this._wrapClientCallback
(callback)); | |
| 1808 }, | |
| 1809 | |
| 1810 /** | |
| 1811 * @param {!DOMAgent.NodeId=} nodeId | |
| 1812 * @param {string=} mode | |
| 1813 * @param {!DOMAgent.BackendNodeId=} backendNodeId | |
| 1814 * @param {!RuntimeAgent.RemoteObjectId=} objectId | |
| 1815 */ | |
| 1816 highlightDOMNode: function(nodeId, mode, backendNodeId, objectId) | |
| 1817 { | |
| 1818 this.highlightDOMNodeWithConfig(nodeId, { mode: mode }, backendNodeId, o
bjectId); | |
| 1819 }, | |
| 1820 | |
| 1821 /** | |
| 1822 * @param {!DOMAgent.NodeId=} nodeId | |
| 1823 * @param {!{mode: (string|undefined), showInfo: (boolean|undefined), select
ors: (string|undefined)}=} config | |
| 1824 * @param {!DOMAgent.BackendNodeId=} backendNodeId | |
| 1825 * @param {!RuntimeAgent.RemoteObjectId=} objectId | |
| 1826 */ | |
| 1827 highlightDOMNodeWithConfig: function(nodeId, config, backendNodeId, objectId
) | |
| 1828 { | |
| 1829 if (WebInspector.DOMModel._highlightDisabled) | |
| 1830 return; | |
| 1831 config = config || { mode: "all", showInfo: undefined, selectors: undefi
ned }; | |
| 1832 if (this._hideDOMNodeHighlightTimeout) { | |
| 1833 clearTimeout(this._hideDOMNodeHighlightTimeout); | |
| 1834 delete this._hideDOMNodeHighlightTimeout; | |
| 1835 } | |
| 1836 var highlightConfig = this._buildHighlightConfig(config.mode); | |
| 1837 if (typeof config.showInfo !== "undefined") | |
| 1838 highlightConfig.showInfo = config.showInfo; | |
| 1839 if (typeof config.selectors !== "undefined") | |
| 1840 highlightConfig.selectorList = config.selectors; | |
| 1841 this._highlighter.highlightDOMNode(this.nodeForId(nodeId || 0), highligh
tConfig, backendNodeId, objectId); | |
| 1842 }, | |
| 1843 | |
| 1844 /** | |
| 1845 * @param {!DOMAgent.NodeId} nodeId | |
| 1846 */ | |
| 1847 highlightDOMNodeForTwoSeconds: function(nodeId) | |
| 1848 { | |
| 1849 this.highlightDOMNode(nodeId); | |
| 1850 this._hideDOMNodeHighlightTimeout = setTimeout(WebInspector.DOMModel.hid
eDOMNodeHighlight.bind(WebInspector.DOMModel), 2000); | |
| 1851 }, | |
| 1852 | |
| 1853 /** | |
| 1854 * @param {!PageAgent.FrameId} frameId | |
| 1855 */ | |
| 1856 highlightFrame: function(frameId) | |
| 1857 { | |
| 1858 if (WebInspector.DOMModel._highlightDisabled) | |
| 1859 return; | |
| 1860 this._highlighter.highlightFrame(frameId); | |
| 1861 }, | |
| 1862 | |
| 1863 /** | |
| 1864 * @param {!DOMAgent.InspectMode} mode | |
| 1865 * @param {function(?Protocol.Error)=} callback | |
| 1866 */ | |
| 1867 setInspectMode: function(mode, callback) | |
| 1868 { | |
| 1869 /** | |
| 1870 * @this {WebInspector.DOMModel} | |
| 1871 */ | |
| 1872 function onDocumentAvailable() | |
| 1873 { | |
| 1874 this._inspectModeEnabled = mode !== DOMAgent.InspectMode.None; | |
| 1875 this.dispatchEventToListeners(WebInspector.DOMModel.Events.InspectMo
deWillBeToggled, this._inspectModeEnabled); | |
| 1876 this._highlighter.setInspectMode(mode, this._buildHighlightConfig(),
callback); | |
| 1877 } | |
| 1878 this.requestDocument(onDocumentAvailable.bind(this)); | |
| 1879 }, | |
| 1880 | |
| 1881 /** | |
| 1882 * @return {boolean} | |
| 1883 */ | |
| 1884 inspectModeEnabled: function() | |
| 1885 { | |
| 1886 return this._inspectModeEnabled; | |
| 1887 }, | |
| 1888 | |
| 1889 /** | |
| 1890 * @param {string=} mode | |
| 1891 * @return {!DOMAgent.HighlightConfig} | |
| 1892 */ | |
| 1893 _buildHighlightConfig: function(mode) | |
| 1894 { | |
| 1895 mode = mode || "all"; | |
| 1896 var showRulers = WebInspector.moduleSetting("showMetricsRulers").get(); | |
| 1897 var highlightConfig = { showInfo: mode === "all", showRulers: showRulers
, showExtensionLines: showRulers }; | |
| 1898 if (mode === "all" || mode === "content") | |
| 1899 highlightConfig.contentColor = WebInspector.Color.PageHighlight.Cont
ent.toProtocolRGBA(); | |
| 1900 | |
| 1901 if (mode === "all" || mode === "padding") | |
| 1902 highlightConfig.paddingColor = WebInspector.Color.PageHighlight.Padd
ing.toProtocolRGBA(); | |
| 1903 | |
| 1904 if (mode === "all" || mode === "border") | |
| 1905 highlightConfig.borderColor = WebInspector.Color.PageHighlight.Borde
r.toProtocolRGBA(); | |
| 1906 | |
| 1907 if (mode === "all" || mode === "margin") | |
| 1908 highlightConfig.marginColor = WebInspector.Color.PageHighlight.Margi
n.toProtocolRGBA(); | |
| 1909 | |
| 1910 if (mode === "all") { | |
| 1911 highlightConfig.eventTargetColor = WebInspector.Color.PageHighlight.
EventTarget.toProtocolRGBA(); | |
| 1912 highlightConfig.shapeColor = WebInspector.Color.PageHighlight.Shape.
toProtocolRGBA(); | |
| 1913 highlightConfig.shapeMarginColor = WebInspector.Color.PageHighlight.
ShapeMargin.toProtocolRGBA(); | |
| 1914 highlightConfig.displayAsMaterial = Runtime.experiments.isEnabled("i
nspectTooltip"); | |
| 1915 } | |
| 1916 return highlightConfig; | |
| 1917 }, | |
| 1918 | |
| 1919 /** | |
| 1920 * @param {!WebInspector.DOMNode} node | |
| 1921 * @param {function(?Protocol.Error, ...)=} callback | |
| 1922 * @return {function(...)} | |
| 1923 * @template T | |
| 1924 */ | |
| 1925 _markRevision: function(node, callback) | |
| 1926 { | |
| 1927 /** | |
| 1928 * @param {?Protocol.Error} error | |
| 1929 * @this {WebInspector.DOMModel} | |
| 1930 */ | |
| 1931 function wrapperFunction(error) | |
| 1932 { | |
| 1933 if (!error) | |
| 1934 this.markUndoableState(); | |
| 1935 | |
| 1936 if (callback) | |
| 1937 callback.apply(this, arguments); | |
| 1938 } | |
| 1939 return wrapperFunction.bind(this); | |
| 1940 }, | |
| 1941 | |
| 1942 markUndoableState: function() | |
| 1943 { | |
| 1944 this._agent.markUndoableState(); | |
| 1945 }, | |
| 1946 | |
| 1947 /** | |
| 1948 * @param {function(?Protocol.Error)=} callback | |
| 1949 */ | |
| 1950 undo: function(callback) | |
| 1951 { | |
| 1952 /** | |
| 1953 * @param {?Protocol.Error} error | |
| 1954 * @this {WebInspector.DOMModel} | |
| 1955 */ | |
| 1956 function mycallback(error) | |
| 1957 { | |
| 1958 this.dispatchEventToListeners(WebInspector.DOMModel.Events.UndoRedoC
ompleted); | |
| 1959 callback(error); | |
| 1960 } | |
| 1961 | |
| 1962 this.dispatchEventToListeners(WebInspector.DOMModel.Events.UndoRedoReque
sted); | |
| 1963 this._agent.undo(callback); | |
| 1964 }, | |
| 1965 | |
| 1966 /** | |
| 1967 * @param {function(?Protocol.Error)=} callback | |
| 1968 */ | |
| 1969 redo: function(callback) | |
| 1970 { | |
| 1971 /** | |
| 1972 * @param {?Protocol.Error} error | |
| 1973 * @this {WebInspector.DOMModel} | |
| 1974 */ | |
| 1975 function mycallback(error) | |
| 1976 { | |
| 1977 this.dispatchEventToListeners(WebInspector.DOMModel.Events.UndoRedoC
ompleted); | |
| 1978 callback(error); | |
| 1979 } | |
| 1980 | |
| 1981 this.dispatchEventToListeners(WebInspector.DOMModel.Events.UndoRedoReque
sted); | |
| 1982 this._agent.redo(callback); | |
| 1983 }, | |
| 1984 | |
| 1985 /** | |
| 1986 * @param {?WebInspector.DOMNodeHighlighter} highlighter | |
| 1987 */ | |
| 1988 setHighlighter: function(highlighter) | |
| 1989 { | |
| 1990 this._highlighter = highlighter || this._defaultHighlighter; | |
| 1991 }, | |
| 1992 | |
| 1993 /** | |
| 1994 * @param {number} x | |
| 1995 * @param {number} y | |
| 1996 * @param {function(?WebInspector.DOMNode)} callback | |
| 1997 */ | |
| 1998 nodeForLocation: function(x, y, callback) | |
| 1999 { | |
| 2000 this._agent.getNodeForLocation(x, y, mycallback.bind(this)); | |
| 2001 | |
| 2002 /** | |
| 2003 * @param {?Protocol.Error} error | |
| 2004 * @param {number} nodeId | |
| 2005 * @this {WebInspector.DOMModel} | |
| 2006 */ | |
| 2007 function mycallback(error, nodeId) | |
| 2008 { | |
| 2009 if (error) { | |
| 2010 callback(null); | |
| 2011 return; | |
| 2012 } | |
| 2013 callback(this.nodeForId(nodeId)); | |
| 2014 } | |
| 2015 }, | |
| 2016 | |
| 2017 /** | |
| 2018 * @param {!WebInspector.RemoteObject} object | |
| 2019 * @param {function(?WebInspector.DOMNode)} callback | |
| 2020 */ | |
| 2021 pushObjectAsNodeToFrontend: function(object, callback) | |
| 2022 { | |
| 2023 if (object.isNode()) | |
| 2024 this.pushNodeToFrontend(object.objectId, callback); | |
| 2025 else | |
| 2026 callback(null); | |
| 2027 }, | |
| 2028 | |
| 2029 /** | |
| 2030 * @override | |
| 2031 * @return {!Promise} | |
| 2032 */ | |
| 2033 suspendModel: function() | |
| 2034 { | |
| 2035 return new Promise(promiseBody.bind(this)); | |
| 2036 | |
| 2037 /** | |
| 2038 * @param {function()} fulfill | |
| 2039 * @this {WebInspector.DOMModel} | |
| 2040 */ | |
| 2041 function promiseBody(fulfill) | |
| 2042 { | |
| 2043 this._agent.disable(callback.bind(this)); | |
| 2044 | |
| 2045 /** | |
| 2046 * @this {WebInspector.DOMModel} | |
| 2047 */ | |
| 2048 function callback() | |
| 2049 { | |
| 2050 this._setDocument(null); | |
| 2051 fulfill(); | |
| 2052 } | |
| 2053 } | |
| 2054 }, | |
| 2055 | |
| 2056 /** | |
| 2057 * @override | |
| 2058 * @return {!Promise} | |
| 2059 */ | |
| 2060 resumeModel: function() | |
| 2061 { | |
| 2062 return new Promise(promiseBody.bind(this)); | |
| 2063 | |
| 2064 /** | |
| 2065 * @param {function()} fulfill | |
| 2066 * @this {WebInspector.DOMModel} | |
| 2067 */ | |
| 2068 function promiseBody(fulfill) | |
| 2069 { | |
| 2070 this._agent.enable(fulfill); | |
| 2071 } | |
| 2072 }, | |
| 2073 | |
| 2074 /** | |
| 2075 * @param {!DOMAgent.NodeId} nodeId | |
| 2076 */ | |
| 2077 nodeHighlightRequested: function(nodeId) | |
| 2078 { | |
| 2079 var node = this.nodeForId(nodeId); | |
| 2080 if (!node) | |
| 2081 return; | |
| 2082 | |
| 2083 this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeHighlight
edInOverlay, node); | |
| 2084 }, | |
| 2085 | |
| 2086 __proto__: WebInspector.SDKModel.prototype | |
| 2087 }; | |
| 2088 | |
| 2089 /** | |
| 2090 * @constructor | |
| 2091 * @implements {DOMAgent.Dispatcher} | |
| 2092 * @param {!WebInspector.DOMModel} domModel | |
| 2093 */ | |
| 2094 WebInspector.DOMDispatcher = function(domModel) | |
| 2095 { | |
| 2096 this._domModel = domModel; | 1948 this._domModel = domModel; |
| 2097 }; | 1949 } |
| 2098 | 1950 |
| 2099 WebInspector.DOMDispatcher.prototype = { | 1951 /** |
| 2100 /** | 1952 * @override |
| 2101 * @override | 1953 */ |
| 2102 */ | 1954 documentUpdated() { |
| 2103 documentUpdated: function() | 1955 this._domModel._documentUpdated(); |
| 2104 { | 1956 } |
| 2105 this._domModel._documentUpdated(); | 1957 |
| 2106 }, | 1958 /** |
| 2107 | 1959 * @override |
| 2108 /** | 1960 * @param {!DOMAgent.NodeId} nodeId |
| 2109 * @override | 1961 */ |
| 2110 * @param {!DOMAgent.NodeId} nodeId | 1962 inspectNodeRequested(nodeId) { |
| 2111 */ | 1963 this._domModel._inspectNodeRequested(nodeId); |
| 2112 inspectNodeRequested: function(nodeId) | 1964 } |
| 2113 { | 1965 |
| 2114 this._domModel._inspectNodeRequested(nodeId); | 1966 /** |
| 2115 }, | 1967 * @override |
| 2116 | 1968 * @param {!DOMAgent.NodeId} nodeId |
| 2117 /** | 1969 * @param {string} name |
| 2118 * @override | 1970 * @param {string} value |
| 2119 * @param {!DOMAgent.NodeId} nodeId | 1971 */ |
| 2120 * @param {string} name | 1972 attributeModified(nodeId, name, value) { |
| 2121 * @param {string} value | 1973 this._domModel._attributeModified(nodeId, name, value); |
| 2122 */ | 1974 } |
| 2123 attributeModified: function(nodeId, name, value) | 1975 |
| 2124 { | 1976 /** |
| 2125 this._domModel._attributeModified(nodeId, name, value); | 1977 * @override |
| 2126 }, | 1978 * @param {!DOMAgent.NodeId} nodeId |
| 2127 | 1979 * @param {string} name |
| 2128 /** | 1980 */ |
| 2129 * @override | 1981 attributeRemoved(nodeId, name) { |
| 2130 * @param {!DOMAgent.NodeId} nodeId | 1982 this._domModel._attributeRemoved(nodeId, name); |
| 2131 * @param {string} name | 1983 } |
| 2132 */ | 1984 |
| 2133 attributeRemoved: function(nodeId, name) | 1985 /** |
| 2134 { | 1986 * @override |
| 2135 this._domModel._attributeRemoved(nodeId, name); | 1987 * @param {!Array.<!DOMAgent.NodeId>} nodeIds |
| 2136 }, | 1988 */ |
| 2137 | 1989 inlineStyleInvalidated(nodeIds) { |
| 2138 /** | 1990 this._domModel._inlineStyleInvalidated(nodeIds); |
| 2139 * @override | 1991 } |
| 2140 * @param {!Array.<!DOMAgent.NodeId>} nodeIds | 1992 |
| 2141 */ | 1993 /** |
| 2142 inlineStyleInvalidated: function(nodeIds) | 1994 * @override |
| 2143 { | 1995 * @param {!DOMAgent.NodeId} nodeId |
| 2144 this._domModel._inlineStyleInvalidated(nodeIds); | 1996 * @param {string} characterData |
| 2145 }, | 1997 */ |
| 2146 | 1998 characterDataModified(nodeId, characterData) { |
| 2147 /** | 1999 this._domModel._characterDataModified(nodeId, characterData); |
| 2148 * @override | 2000 } |
| 2149 * @param {!DOMAgent.NodeId} nodeId | 2001 |
| 2150 * @param {string} characterData | 2002 /** |
| 2151 */ | 2003 * @override |
| 2152 characterDataModified: function(nodeId, characterData) | 2004 * @param {!DOMAgent.NodeId} parentId |
| 2153 { | 2005 * @param {!Array.<!DOMAgent.Node>} payloads |
| 2154 this._domModel._characterDataModified(nodeId, characterData); | 2006 */ |
| 2155 }, | 2007 setChildNodes(parentId, payloads) { |
| 2156 | 2008 this._domModel._setChildNodes(parentId, payloads); |
| 2157 /** | 2009 } |
| 2158 * @override | 2010 |
| 2159 * @param {!DOMAgent.NodeId} parentId | 2011 /** |
| 2160 * @param {!Array.<!DOMAgent.Node>} payloads | 2012 * @override |
| 2161 */ | 2013 * @param {!DOMAgent.NodeId} nodeId |
| 2162 setChildNodes: function(parentId, payloads) | 2014 * @param {number} childNodeCount |
| 2163 { | 2015 */ |
| 2164 this._domModel._setChildNodes(parentId, payloads); | 2016 childNodeCountUpdated(nodeId, childNodeCount) { |
| 2165 }, | 2017 this._domModel._childNodeCountUpdated(nodeId, childNodeCount); |
| 2166 | 2018 } |
| 2167 /** | 2019 |
| 2168 * @override | 2020 /** |
| 2169 * @param {!DOMAgent.NodeId} nodeId | 2021 * @override |
| 2170 * @param {number} childNodeCount | 2022 * @param {!DOMAgent.NodeId} parentNodeId |
| 2171 */ | 2023 * @param {!DOMAgent.NodeId} previousNodeId |
| 2172 childNodeCountUpdated: function(nodeId, childNodeCount) | 2024 * @param {!DOMAgent.Node} payload |
| 2173 { | 2025 */ |
| 2174 this._domModel._childNodeCountUpdated(nodeId, childNodeCount); | 2026 childNodeInserted(parentNodeId, previousNodeId, payload) { |
| 2175 }, | 2027 this._domModel._childNodeInserted(parentNodeId, previousNodeId, payload); |
| 2176 | 2028 } |
| 2177 /** | 2029 |
| 2178 * @override | 2030 /** |
| 2179 * @param {!DOMAgent.NodeId} parentNodeId | 2031 * @override |
| 2180 * @param {!DOMAgent.NodeId} previousNodeId | 2032 * @param {!DOMAgent.NodeId} parentNodeId |
| 2181 * @param {!DOMAgent.Node} payload | 2033 * @param {!DOMAgent.NodeId} nodeId |
| 2182 */ | 2034 */ |
| 2183 childNodeInserted: function(parentNodeId, previousNodeId, payload) | 2035 childNodeRemoved(parentNodeId, nodeId) { |
| 2184 { | 2036 this._domModel._childNodeRemoved(parentNodeId, nodeId); |
| 2185 this._domModel._childNodeInserted(parentNodeId, previousNodeId, payload)
; | 2037 } |
| 2186 }, | 2038 |
| 2187 | 2039 /** |
| 2188 /** | 2040 * @override |
| 2189 * @override | 2041 * @param {!DOMAgent.NodeId} hostId |
| 2190 * @param {!DOMAgent.NodeId} parentNodeId | 2042 * @param {!DOMAgent.Node} root |
| 2191 * @param {!DOMAgent.NodeId} nodeId | 2043 */ |
| 2192 */ | 2044 shadowRootPushed(hostId, root) { |
| 2193 childNodeRemoved: function(parentNodeId, nodeId) | 2045 this._domModel._shadowRootPushed(hostId, root); |
| 2194 { | 2046 } |
| 2195 this._domModel._childNodeRemoved(parentNodeId, nodeId); | 2047 |
| 2196 }, | 2048 /** |
| 2197 | 2049 * @override |
| 2198 /** | 2050 * @param {!DOMAgent.NodeId} hostId |
| 2199 * @override | 2051 * @param {!DOMAgent.NodeId} rootId |
| 2200 * @param {!DOMAgent.NodeId} hostId | 2052 */ |
| 2201 * @param {!DOMAgent.Node} root | 2053 shadowRootPopped(hostId, rootId) { |
| 2202 */ | 2054 this._domModel._shadowRootPopped(hostId, rootId); |
| 2203 shadowRootPushed: function(hostId, root) | 2055 } |
| 2204 { | 2056 |
| 2205 this._domModel._shadowRootPushed(hostId, root); | 2057 /** |
| 2206 }, | 2058 * @override |
| 2207 | 2059 * @param {!DOMAgent.NodeId} parentId |
| 2208 /** | 2060 * @param {!DOMAgent.Node} pseudoElement |
| 2209 * @override | 2061 */ |
| 2210 * @param {!DOMAgent.NodeId} hostId | 2062 pseudoElementAdded(parentId, pseudoElement) { |
| 2211 * @param {!DOMAgent.NodeId} rootId | 2063 this._domModel._pseudoElementAdded(parentId, pseudoElement); |
| 2212 */ | 2064 } |
| 2213 shadowRootPopped: function(hostId, rootId) | 2065 |
| 2214 { | 2066 /** |
| 2215 this._domModel._shadowRootPopped(hostId, rootId); | 2067 * @override |
| 2216 }, | 2068 * @param {!DOMAgent.NodeId} parentId |
| 2217 | 2069 * @param {!DOMAgent.NodeId} pseudoElementId |
| 2218 /** | 2070 */ |
| 2219 * @override | 2071 pseudoElementRemoved(parentId, pseudoElementId) { |
| 2220 * @param {!DOMAgent.NodeId} parentId | 2072 this._domModel._pseudoElementRemoved(parentId, pseudoElementId); |
| 2221 * @param {!DOMAgent.Node} pseudoElement | 2073 } |
| 2222 */ | 2074 |
| 2223 pseudoElementAdded: function(parentId, pseudoElement) | 2075 /** |
| 2224 { | 2076 * @override |
| 2225 this._domModel._pseudoElementAdded(parentId, pseudoElement); | 2077 * @param {!DOMAgent.NodeId} insertionPointId |
| 2226 }, | 2078 * @param {!Array.<!DOMAgent.BackendNode>} distributedNodes |
| 2227 | 2079 */ |
| 2228 /** | 2080 distributedNodesUpdated(insertionPointId, distributedNodes) { |
| 2229 * @override | 2081 this._domModel._distributedNodesUpdated(insertionPointId, distributedNodes); |
| 2230 * @param {!DOMAgent.NodeId} parentId | 2082 } |
| 2231 * @param {!DOMAgent.NodeId} pseudoElementId | 2083 |
| 2232 */ | 2084 /** |
| 2233 pseudoElementRemoved: function(parentId, pseudoElementId) | 2085 * @override |
| 2234 { | 2086 * @param {!DOMAgent.NodeId} nodeId |
| 2235 this._domModel._pseudoElementRemoved(parentId, pseudoElementId); | 2087 */ |
| 2236 }, | 2088 nodeHighlightRequested(nodeId) { |
| 2237 | 2089 this._domModel.nodeHighlightRequested(nodeId); |
| 2238 /** | 2090 } |
| 2239 * @override | |
| 2240 * @param {!DOMAgent.NodeId} insertionPointId | |
| 2241 * @param {!Array.<!DOMAgent.BackendNode>} distributedNodes | |
| 2242 */ | |
| 2243 distributedNodesUpdated: function(insertionPointId, distributedNodes) | |
| 2244 { | |
| 2245 this._domModel._distributedNodesUpdated(insertionPointId, distributedNod
es); | |
| 2246 }, | |
| 2247 | |
| 2248 /** | |
| 2249 * @override | |
| 2250 * @param {!DOMAgent.NodeId} nodeId | |
| 2251 */ | |
| 2252 nodeHighlightRequested: function(nodeId) | |
| 2253 { | |
| 2254 this._domModel.nodeHighlightRequested(nodeId); | |
| 2255 } | |
| 2256 }; | 2091 }; |
| 2257 | 2092 |
| 2258 /** | 2093 /** |
| 2259 * @interface | 2094 * @interface |
| 2260 */ | 2095 */ |
| 2261 WebInspector.DOMNodeHighlighter = function() { | 2096 WebInspector.DOMNodeHighlighter = function() {}; |
| 2097 |
| 2098 WebInspector.DOMNodeHighlighter.prototype = { |
| 2099 /** |
| 2100 * @param {?WebInspector.DOMNode} node |
| 2101 * @param {!DOMAgent.HighlightConfig} config |
| 2102 * @param {!DOMAgent.BackendNodeId=} backendNodeId |
| 2103 * @param {!RuntimeAgent.RemoteObjectId=} objectId |
| 2104 */ |
| 2105 highlightDOMNode: function(node, config, backendNodeId, objectId) {}, |
| 2106 |
| 2107 /** |
| 2108 * @param {!DOMAgent.InspectMode} mode |
| 2109 * @param {!DOMAgent.HighlightConfig} config |
| 2110 * @param {function(?Protocol.Error)=} callback |
| 2111 */ |
| 2112 setInspectMode: function(mode, config, callback) {}, |
| 2113 |
| 2114 /** |
| 2115 * @param {!PageAgent.FrameId} frameId |
| 2116 */ |
| 2117 highlightFrame: function(frameId) {} |
| 2262 }; | 2118 }; |
| 2263 | 2119 |
| 2264 WebInspector.DOMNodeHighlighter.prototype = { | 2120 /** |
| 2265 /** | 2121 * @implements {WebInspector.DOMNodeHighlighter} |
| 2266 * @param {?WebInspector.DOMNode} node | 2122 * @unrestricted |
| 2267 * @param {!DOMAgent.HighlightConfig} config | 2123 */ |
| 2268 * @param {!DOMAgent.BackendNodeId=} backendNodeId | 2124 WebInspector.DefaultDOMNodeHighlighter = class { |
| 2269 * @param {!RuntimeAgent.RemoteObjectId=} objectId | 2125 /** |
| 2270 */ | 2126 * @param {!Protocol.DOMAgent} agent |
| 2271 highlightDOMNode: function(node, config, backendNodeId, objectId) {}, | 2127 */ |
| 2272 | 2128 constructor(agent) { |
| 2273 /** | 2129 this._agent = agent; |
| 2274 * @param {!DOMAgent.InspectMode} mode | 2130 } |
| 2275 * @param {!DOMAgent.HighlightConfig} config | 2131 |
| 2276 * @param {function(?Protocol.Error)=} callback | 2132 /** |
| 2277 */ | 2133 * @override |
| 2278 setInspectMode: function(mode, config, callback) {}, | 2134 * @param {?WebInspector.DOMNode} node |
| 2279 | 2135 * @param {!DOMAgent.HighlightConfig} config |
| 2280 /** | 2136 * @param {!DOMAgent.BackendNodeId=} backendNodeId |
| 2281 * @param {!PageAgent.FrameId} frameId | 2137 * @param {!RuntimeAgent.RemoteObjectId=} objectId |
| 2282 */ | 2138 */ |
| 2283 highlightFrame: function(frameId) {} | 2139 highlightDOMNode(node, config, backendNodeId, objectId) { |
| 2140 if (objectId || node || backendNodeId) |
| 2141 this._agent.highlightNode(config, (objectId || backendNodeId) ? undefined
: node.id, backendNodeId, objectId); |
| 2142 else |
| 2143 this._agent.hideHighlight(); |
| 2144 } |
| 2145 |
| 2146 /** |
| 2147 * @override |
| 2148 * @param {!DOMAgent.InspectMode} mode |
| 2149 * @param {!DOMAgent.HighlightConfig} config |
| 2150 * @param {function(?Protocol.Error)=} callback |
| 2151 */ |
| 2152 setInspectMode(mode, config, callback) { |
| 2153 this._agent.setInspectMode(mode, config, callback); |
| 2154 } |
| 2155 |
| 2156 /** |
| 2157 * @override |
| 2158 * @param {!PageAgent.FrameId} frameId |
| 2159 */ |
| 2160 highlightFrame(frameId) { |
| 2161 this._agent.highlightFrame( |
| 2162 frameId, WebInspector.Color.PageHighlight.Content.toProtocolRGBA(), |
| 2163 WebInspector.Color.PageHighlight.ContentOutline.toProtocolRGBA()); |
| 2164 } |
| 2284 }; | 2165 }; |
| 2285 | 2166 |
| 2286 /** | 2167 |
| 2287 * @constructor | |
| 2288 * @implements {WebInspector.DOMNodeHighlighter} | |
| 2289 * @param {!Protocol.DOMAgent} agent | |
| 2290 */ | |
| 2291 WebInspector.DefaultDOMNodeHighlighter = function(agent) | |
| 2292 { | |
| 2293 this._agent = agent; | |
| 2294 }; | |
| 2295 | |
| 2296 WebInspector.DefaultDOMNodeHighlighter.prototype = { | |
| 2297 /** | |
| 2298 * @override | |
| 2299 * @param {?WebInspector.DOMNode} node | |
| 2300 * @param {!DOMAgent.HighlightConfig} config | |
| 2301 * @param {!DOMAgent.BackendNodeId=} backendNodeId | |
| 2302 * @param {!RuntimeAgent.RemoteObjectId=} objectId | |
| 2303 */ | |
| 2304 highlightDOMNode: function(node, config, backendNodeId, objectId) | |
| 2305 { | |
| 2306 if (objectId || node || backendNodeId) | |
| 2307 this._agent.highlightNode(config, (objectId || backendNodeId) ? unde
fined : node.id, backendNodeId, objectId); | |
| 2308 else | |
| 2309 this._agent.hideHighlight(); | |
| 2310 }, | |
| 2311 | |
| 2312 /** | |
| 2313 * @override | |
| 2314 * @param {!DOMAgent.InspectMode} mode | |
| 2315 * @param {!DOMAgent.HighlightConfig} config | |
| 2316 * @param {function(?Protocol.Error)=} callback | |
| 2317 */ | |
| 2318 setInspectMode: function(mode, config, callback) | |
| 2319 { | |
| 2320 this._agent.setInspectMode(mode, config, callback); | |
| 2321 }, | |
| 2322 | |
| 2323 /** | |
| 2324 * @override | |
| 2325 * @param {!PageAgent.FrameId} frameId | |
| 2326 */ | |
| 2327 highlightFrame: function(frameId) | |
| 2328 { | |
| 2329 this._agent.highlightFrame(frameId, WebInspector.Color.PageHighlight.Con
tent.toProtocolRGBA(), WebInspector.Color.PageHighlight.ContentOutline.toProtoco
lRGBA()); | |
| 2330 } | |
| 2331 }; | |
| 2332 | |
| 2333 /** | |
| 2334 * @param {!WebInspector.Target} target | |
| 2335 * @return {?WebInspector.DOMModel} | |
| 2336 */ | |
| 2337 WebInspector.DOMModel.fromTarget = function(target) | |
| 2338 { | |
| 2339 return /** @type {?WebInspector.DOMModel} */ (target.model(WebInspector.DOMM
odel)); | |
| 2340 }; | |
| OLD | NEW |