Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(64)

Side by Side Diff: Source/devtools/front_end/DOMAgent.js

Issue 16561003: DevTools: Inspect element mode does not select element in ShadowDOM (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 this._shadowRoots = []; 51 this._shadowRoots = [];
52 52
53 this._attributes = []; 53 this._attributes = [];
54 this._attributesMap = {}; 54 this._attributesMap = {};
55 if (payload.attributes) 55 if (payload.attributes)
56 this._setAttributesPayload(payload.attributes); 56 this._setAttributesPayload(payload.attributes);
57 57
58 this._userProperties = {}; 58 this._userProperties = {};
59 this._descendantUserPropertyCounters = {}; 59 this._descendantUserPropertyCounters = {};
60 60
61 this._childNodeCount = payload.childNodeCount; 61 this._childNodeCount = payload.childNodeCount || 0;
62 this.children = null; 62 this._children = null;
63 63
64 this.nextSibling = null; 64 this.nextSibling = null;
65 this.previousSibling = null; 65 this.previousSibling = null;
66 this.firstChild = null; 66 this.firstChild = null;
67 this.lastChild = null; 67 this.lastChild = null;
68 this.parentNode = null; 68 this.parentNode = null;
69 69
70 if (payload.shadowRoots && WebInspector.settings.showShadowDOM.get()) { 70 if (payload.shadowRoots) {
71 for (var i = 0; i < payload.shadowRoots.length; ++i) { 71 for (var i = 0; i < payload.shadowRoots.length; ++i) {
72 var root = payload.shadowRoots[i]; 72 var root = payload.shadowRoots[i];
73 var node = new WebInspector.DOMNode(this._domAgent, this.ownerDocume nt, true, root); 73 var node = new WebInspector.DOMNode(this._domAgent, this.ownerDocume nt, true, root);
74 this._shadowRoots.push(node); 74 this._shadowRoots.push(node);
75 node.parentNode = this;
75 } 76 }
76 } 77 }
77 78
78 if (payload.templateContent) 79 if (payload.templateContent) {
79 this._templateContent = new WebInspector.DOMNode(this._domAgent, this.ow nerDocument, true, payload.templateContent); 80 this._templateContent = new WebInspector.DOMNode(this._domAgent, this.ow nerDocument, true, payload.templateContent);
81 this._templateContent.parentNode = this;
82 }
80 83
81 if (payload.children) 84 if (payload.children)
82 this._setChildrenPayload(payload.children); 85 this._setChildrenPayload(payload.children);
83 86
84 if (payload.contentDocument) { 87 if (payload.contentDocument) {
85 this._contentDocument = new WebInspector.DOMDocument(domAgent, payload.c ontentDocument); 88 this._contentDocument = new WebInspector.DOMDocument(domAgent, payload.c ontentDocument);
86 this.children = [this._contentDocument]; 89 this._children = [this._contentDocument];
87 this._renumber(); 90 this._renumber();
88 } 91 }
89 92
90 if (this._nodeType === Node.ELEMENT_NODE) { 93 if (this._nodeType === Node.ELEMENT_NODE) {
91 // HTML and BODY from internal iframes should not overwrite top-level on es. 94 // HTML and BODY from internal iframes should not overwrite top-level on es.
92 if (this.ownerDocument && !this.ownerDocument.documentElement && this._n odeName === "HTML") 95 if (this.ownerDocument && !this.ownerDocument.documentElement && this._n odeName === "HTML")
93 this.ownerDocument.documentElement = this; 96 this.ownerDocument.documentElement = this;
94 if (this.ownerDocument && !this.ownerDocument.body && this._nodeName === "BODY") 97 if (this.ownerDocument && !this.ownerDocument.body && this._nodeName === "BODY")
95 this.ownerDocument.body = this; 98 this.ownerDocument.body = this;
96 } else if (this._nodeType === Node.DOCUMENT_TYPE_NODE) { 99 } else if (this._nodeType === Node.DOCUMENT_TYPE_NODE) {
(...skipping 19 matching lines...) Expand all
116 119
117 WebInspector.DOMNode.XPathStep.prototype = { 120 WebInspector.DOMNode.XPathStep.prototype = {
118 toString: function() 121 toString: function()
119 { 122 {
120 return this.value; 123 return this.value;
121 } 124 }
122 } 125 }
123 126
124 WebInspector.DOMNode.prototype = { 127 WebInspector.DOMNode.prototype = {
125 /** 128 /**
129 * @return {Array.<WebInspector.DOMNode>}
130 */
131 children: function()
132 {
133 return this._children;
134 },
135
136 /**
126 * @return {boolean} 137 * @return {boolean}
127 */ 138 */
128 hasAttributes: function() 139 hasAttributes: function()
129 { 140 {
130 return this._attributes.length > 0; 141 return this._attributes.length > 0;
131 }, 142 },
132 143
133 /** 144 /**
134 * @return {boolean} 145 * @return {number}
135 */ 146 */
136 hasChildNodes: function() 147 childNodeCount: function()
137 { 148 {
138 return this._childNodeCount > 0 || !!this._shadowRoots.length || !!this. _templateContent; 149 return this._childNodeCount;
139 }, 150 },
140 151
141 /** 152 /**
142 * @return {boolean} 153 * @return {boolean}
143 */ 154 */
144 hasShadowRoots: function() 155 hasShadowRoots: function()
145 { 156 {
146 return !!this._shadowRoots.length; 157 return !!this._shadowRoots.length;
147 }, 158 },
148 159
149 /** 160 /**
161 * @return {Array.<WebInspector.DOMNode>}
162 */
163 shadowRoots: function()
164 {
165 return this._shadowRoots;
166 },
167
168 /**
169 * @return {WebInspector.DOMNode}
170 */
171 templateContent: function()
172 {
173 return this._templateContent;
174 },
175
176 /**
150 * @return {number} 177 * @return {number}
151 */ 178 */
152 nodeType: function() 179 nodeType: function()
153 { 180 {
154 return this._nodeType; 181 return this._nodeType;
155 }, 182 },
156 183
157 /** 184 /**
158 * @return {string} 185 * @return {string}
159 */ 186 */
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 WebInspector.domAgent._markRevision(this, callback)(error); 301 WebInspector.domAgent._markRevision(this, callback)(error);
275 } 302 }
276 DOMAgent.removeAttribute(this.id, name, mycallback.bind(this)); 303 DOMAgent.removeAttribute(this.id, name, mycallback.bind(this));
277 }, 304 },
278 305
279 /** 306 /**
280 * @param {function(Array.<WebInspector.DOMNode>)=} callback 307 * @param {function(Array.<WebInspector.DOMNode>)=} callback
281 */ 308 */
282 getChildNodes: function(callback) 309 getChildNodes: function(callback)
283 { 310 {
284 if (this.children) { 311 if (this._children) {
285 if (callback) 312 if (callback)
286 callback(this.children); 313 callback(this._children);
287 return; 314 return;
288 } 315 }
289 316
290 /** 317 /**
291 * @this {WebInspector.DOMNode} 318 * @this {WebInspector.DOMNode}
292 * @param {?Protocol.Error} error 319 * @param {?Protocol.Error} error
293 */ 320 */
294 function mycallback(error) 321 function mycallback(error)
295 { 322 {
296 if (!error && callback) 323 if (!error && callback)
297 callback(this.children); 324 callback(this._children);
298 } 325 }
299 326
300 DOMAgent.requestChildNodes(this.id, undefined, mycallback.bind(this)); 327 DOMAgent.requestChildNodes(this.id, undefined, mycallback.bind(this));
301 }, 328 },
302 329
303 /** 330 /**
304 * @param {number} depth 331 * @param {number} depth
305 * @param {function(Array.<WebInspector.DOMNode>)=} callback 332 * @param {function(Array.<WebInspector.DOMNode>)=} callback
306 */ 333 */
307 getSubtree: function(depth, callback) 334 getSubtree: function(depth, callback)
308 { 335 {
309 /** 336 /**
310 * @this {WebInspector.DOMNode} 337 * @this {WebInspector.DOMNode}
311 * @param {?Protocol.Error} error 338 * @param {?Protocol.Error} error
312 */ 339 */
313 function mycallback(error) 340 function mycallback(error)
314 { 341 {
315 if (callback) 342 if (callback)
316 callback(error ? null : this.children); 343 callback(error ? null : this._children);
317 } 344 }
318 345
319 DOMAgent.requestChildNodes(this.id, depth, mycallback.bind(this)); 346 DOMAgent.requestChildNodes(this.id, depth, mycallback.bind(this));
320 }, 347 },
321 348
322 /** 349 /**
323 * @param {function(?Protocol.Error)=} callback 350 * @param {function(?Protocol.Error)=} callback
324 */ 351 */
325 getOuterHTML: function(callback) 352 getOuterHTML: function(callback)
326 { 353 {
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 494
468 /** 495 /**
469 * @param {WebInspector.DOMNode} prev 496 * @param {WebInspector.DOMNode} prev
470 * @param {DOMAgent.Node} payload 497 * @param {DOMAgent.Node} payload
471 * @return {WebInspector.DOMNode} 498 * @return {WebInspector.DOMNode}
472 */ 499 */
473 _insertChild: function(prev, payload) 500 _insertChild: function(prev, payload)
474 { 501 {
475 var node = new WebInspector.DOMNode(this._domAgent, this.ownerDocument, this._isInShadowTree, payload); 502 var node = new WebInspector.DOMNode(this._domAgent, this.ownerDocument, this._isInShadowTree, payload);
476 if (!prev) { 503 if (!prev) {
477 if (!this.children) { 504 if (!this._children) {
vsevik 2013/06/07 08:41:00 Impossible, thanks to my || depth check.
pfeldman 2013/06/07 08:53:49 Done.
478 // First node 505 this._children = [];
vsevik 2013/06/07 08:41:00 = [node]
479 this.children = this._shadowRoots.slice(); 506 this._children.push(node);
480 if (this._templateContent)
481 this.children.push(this._templateContent);
482
483 this.children.push(node);
484 } else 507 } else
485 this.children.unshift(node); 508 this._children.unshift(node);
vsevik 2013/06/07 08:41:00 probably not needed
pfeldman 2013/06/07 08:53:49 Done.
486 } else 509 } else
487 this.children.splice(this.children.indexOf(prev) + 1, 0, node); 510 this._children.splice(this._children.indexOf(prev) + 1, 0, node);
488 this._renumber(); 511 this._renumber();
489 return node; 512 return node;
490 }, 513 },
491 514
492 /** 515 /**
493 * @param {WebInspector.DOMNode} node 516 * @param {WebInspector.DOMNode} node
494 */ 517 */
495 _removeChild: function(node) 518 _removeChild: function(node)
496 { 519 {
497 this.children.splice(this.children.indexOf(node), 1); 520 this._children.splice(this._children.indexOf(node), 1);
498 node.parentNode = null; 521 node.parentNode = null;
499 node._updateChildUserPropertyCountsOnRemoval(this); 522 node._updateChildUserPropertyCountsOnRemoval(this);
500 this._renumber(); 523 this._renumber();
501 }, 524 },
502 525
503 /** 526 /**
504 * @param {Array.<DOMAgent.Node>} payloads 527 * @param {Array.<DOMAgent.Node>} payloads
505 */ 528 */
506 _setChildrenPayload: function(payloads) 529 _setChildrenPayload: function(payloads)
507 { 530 {
508 // We set children in the constructor. 531 // We set children in the constructor.
509 if (this._contentDocument) 532 if (this._contentDocument)
510 return; 533 return;
511 534
512 this.children = this._shadowRoots.slice(); 535 this._children = [];
513 if (this._templateContent)
514 this.children.push(this._templateContent);
515
516 for (var i = 0; i < payloads.length; ++i) { 536 for (var i = 0; i < payloads.length; ++i) {
517 var payload = payloads[i]; 537 var payload = payloads[i];
518 var node = new WebInspector.DOMNode(this._domAgent, this.ownerDocume nt, this._isInShadowTree, payload); 538 var node = new WebInspector.DOMNode(this._domAgent, this.ownerDocume nt, this._isInShadowTree, payload);
519 this.children.push(node); 539 this._children.push(node);
520 } 540 }
521 this._renumber(); 541 this._renumber();
522 }, 542 },
523 543
524 _renumber: function() 544 _renumber: function()
525 { 545 {
526 this._childNodeCount = this.children.length; 546 this._childNodeCount = this._children.length;
527 if (this._childNodeCount == 0) { 547 if (this._childNodeCount == 0) {
528 this.firstChild = null; 548 this.firstChild = null;
529 this.lastChild = null; 549 this.lastChild = null;
530 return; 550 return;
531 } 551 }
532 this.firstChild = this.children[0]; 552 this.firstChild = this._children[0];
533 this.lastChild = this.children[this._childNodeCount - 1]; 553 this.lastChild = this._children[this._childNodeCount - 1];
534 for (var i = 0; i < this._childNodeCount; ++i) { 554 for (var i = 0; i < this._childNodeCount; ++i) {
535 var child = this.children[i]; 555 var child = this._children[i];
536 child.index = i; 556 child.index = i;
537 child.nextSibling = i + 1 < this._childNodeCount ? this.children[i + 1] : null; 557 child.nextSibling = i + 1 < this._childNodeCount ? this._children[i + 1] : null;
538 child.previousSibling = i - 1 >= 0 ? this.children[i - 1] : null; 558 child.previousSibling = i - 1 >= 0 ? this._children[i - 1] : null;
539 child.parentNode = this; 559 child.parentNode = this;
540 } 560 }
541 }, 561 },
542 562
543 /** 563 /**
544 * @param {string} name 564 * @param {string} name
545 * @param {string} value 565 * @param {string} value
546 */ 566 */
547 _addAttribute: function(name, value) 567 _addAttribute: function(name, value)
548 { 568 {
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
683 703
684 if (left._nodeType === right._nodeType) 704 if (left._nodeType === right._nodeType)
685 return true; 705 return true;
686 706
687 // XPath treats CDATA as text nodes. 707 // XPath treats CDATA as text nodes.
688 var leftType = left._nodeType === Node.CDATA_SECTION_NODE ? Node.TEX T_NODE : left._nodeType; 708 var leftType = left._nodeType === Node.CDATA_SECTION_NODE ? Node.TEX T_NODE : left._nodeType;
689 var rightType = right._nodeType === Node.CDATA_SECTION_NODE ? Node.T EXT_NODE : right._nodeType; 709 var rightType = right._nodeType === Node.CDATA_SECTION_NODE ? Node.T EXT_NODE : right._nodeType;
690 return leftType === rightType; 710 return leftType === rightType;
691 } 711 }
692 712
693 var siblings = this.parentNode ? this.parentNode.children : null; 713 var siblings = this.parentNode ? this.parentNode._children : null;
694 if (!siblings) 714 if (!siblings)
695 return 0; // Root node - no siblings. 715 return 0; // Root node - no siblings.
696 var hasSameNamedElements; 716 var hasSameNamedElements;
697 for (var i = 0; i < siblings.length; ++i) { 717 for (var i = 0; i < siblings.length; ++i) {
698 if (areNodesSimilar(this, siblings[i]) && siblings[i] !== this) { 718 if (areNodesSimilar(this, siblings[i]) && siblings[i] !== this) {
699 hasSameNamedElements = true; 719 hasSameNamedElements = true;
700 break; 720 break;
701 } 721 }
702 } 722 }
703 if (!hasSameNamedElements) 723 if (!hasSameNamedElements)
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after
1121 _childNodeRemoved: function(parentId, nodeId) 1141 _childNodeRemoved: function(parentId, nodeId)
1122 { 1142 {
1123 var parent = this._idToDOMNode[parentId]; 1143 var parent = this._idToDOMNode[parentId];
1124 var node = this._idToDOMNode[nodeId]; 1144 var node = this._idToDOMNode[nodeId];
1125 parent._removeChild(node); 1145 parent._removeChild(node);
1126 this._unbind(node); 1146 this._unbind(node);
1127 this.dispatchEventToListeners(WebInspector.DOMAgent.Events.NodeRemoved, {node: node, parent: parent}); 1147 this.dispatchEventToListeners(WebInspector.DOMAgent.Events.NodeRemoved, {node: node, parent: parent});
1128 }, 1148 },
1129 1149
1130 /** 1150 /**
1131 * @param {DOMAgent.NodeId} rootId 1151 * @param {DOMAgent.NodeId} hostId
1152 * @param {DOMAgent.Node} root
1132 */ 1153 */
1133 _shadowRootPopped: function(rootId) 1154 _shadowRootPushed: function(hostId, root)
1134 { 1155 {
1156 var host = this._idToDOMNode[hostId];
1157 if (!host)
1158 return;
1159 var node = new WebInspector.DOMNode(this, host.ownerDocument, true, root );
1160 node.parentNode = host;
1161 this._idToDOMNode[node.id] = node;
1162 host._shadowRoots.push(node);
1163 this.dispatchEventToListeners(WebInspector.DOMAgent.Events.NodeInserted, root);
1135 }, 1164 },
1136 1165
1137 /** 1166 /**
1167 * @param {DOMAgent.NodeId} hostId
1168 * @param {DOMAgent.NodeId} rootId
1169 */
1170 _shadowRootPopped: function(hostId, rootId)
1171 {
1172 var host = this._idToDOMNode[hostId];
1173 if (!host)
1174 return;
1175 var root = this._idToDOMNode[rootId];
1176 if (!root)
1177 return;
1178 host._shadowRoots.remove(root);
1179 this._unbind(root);
1180 this.dispatchEventToListeners(WebInspector.DOMAgent.Events.NodeRemoved, {node: root, parent: host});
1181 },
1182
1183 /**
1138 * @param {WebInspector.DOMNode} node 1184 * @param {WebInspector.DOMNode} node
1139 */ 1185 */
1140 _unbind: function(node) 1186 _unbind: function(node)
1141 { 1187 {
1142 delete this._idToDOMNode[node.id]; 1188 delete this._idToDOMNode[node.id];
1143 for (var i = 0; node.children && i < node.children.length; ++i) 1189 for (var i = 0; node._children && i < node._children.length; ++i)
1144 this._unbind(node.children[i]); 1190 this._unbind(node._children[i]);
1191 for (var i = 0; i < node._shadowRoots.length; ++i)
1192 this._unbind(node._shadowRoots[i]);
1193 if (node._templateContent)
1194 this._unbind(node._templateContent);
1145 }, 1195 },
1146 1196
1147 /** 1197 /**
1148 * @param {number} nodeId 1198 * @param {number} nodeId
1149 */ 1199 */
1150 inspectElement: function(nodeId) 1200 inspectElement: function(nodeId)
1151 { 1201 {
1152 var node = this._idToDOMNode[nodeId]; 1202 var node = this._idToDOMNode[nodeId];
1153 if (node) 1203 if (node)
1154 this.dispatchEventToListeners(WebInspector.DOMAgent.Events.InspectEl ementRequested, node); 1204 this.dispatchEventToListeners(WebInspector.DOMAgent.Events.InspectEl ementRequested, node);
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after
1497 { 1547 {
1498 this._domAgent._childNodeRemoved(parentNodeId, nodeId); 1548 this._domAgent._childNodeRemoved(parentNodeId, nodeId);
1499 }, 1549 },
1500 1550
1501 /** 1551 /**
1502 * @param {DOMAgent.NodeId} hostId 1552 * @param {DOMAgent.NodeId} hostId
1503 * @param {DOMAgent.Node} root 1553 * @param {DOMAgent.Node} root
1504 */ 1554 */
1505 shadowRootPushed: function(hostId, root) 1555 shadowRootPushed: function(hostId, root)
1506 { 1556 {
1507 this._domAgent._childNodeInserted(hostId, 0, root); 1557 this._domAgent._shadowRootPushed(hostId, root);
1508 }, 1558 },
1509 1559
1510 /** 1560 /**
1511 * @param {DOMAgent.NodeId} hostId 1561 * @param {DOMAgent.NodeId} hostId
1512 * @param {DOMAgent.NodeId} rootId 1562 * @param {DOMAgent.NodeId} rootId
1513 */ 1563 */
1514 shadowRootPopped: function(hostId, rootId) 1564 shadowRootPopped: function(hostId, rootId)
1515 { 1565 {
1516 this._domAgent._childNodeRemoved(hostId, rootId); 1566 this._domAgent._shadowRootPopped(hostId, rootId);
1517 } 1567 }
1518 } 1568 }
1519 1569
1520 /** 1570 /**
1521 * @type {?WebInspector.DOMAgent} 1571 * @type {?WebInspector.DOMAgent}
1522 */ 1572 */
1523 WebInspector.domAgent = null; 1573 WebInspector.domAgent = null;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698