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

Unified Diff: third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js

Issue 2466123002: DevTools: reformat front-end code to match chromium style. (Closed)
Patch Set: all done Created 4 years, 1 month 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 side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js
index b69f4fdafd9eeb1d9920d8ce07b16846a23f105d..162a03252ad70fcbacd7d36500d0180b8bf8f6d4 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js
@@ -28,2313 +28,2140 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-
/**
- * @constructor
- * @extends {WebInspector.SDKObject}
- * @param {!WebInspector.DOMModel} domModel
+ * @unrestricted
*/
-WebInspector.DOMNode = function(domModel)
-{
- WebInspector.SDKObject.call(this, domModel.target());
+WebInspector.DOMNode = class extends WebInspector.SDKObject {
+ /**
+ * @param {!WebInspector.DOMModel} domModel
+ */
+ constructor(domModel) {
+ super(domModel.target());
this._domModel = domModel;
-};
-
-/**
- * @param {!WebInspector.DOMModel} domModel
- * @param {?WebInspector.DOMDocument} doc
- * @param {boolean} isInShadowTree
- * @param {!DOMAgent.Node} payload
- * @return {!WebInspector.DOMNode}
- */
-WebInspector.DOMNode.create = function(domModel, doc, isInShadowTree, payload)
-{
+ }
+
+ /**
+ * @param {!WebInspector.DOMModel} domModel
+ * @param {?WebInspector.DOMDocument} doc
+ * @param {boolean} isInShadowTree
+ * @param {!DOMAgent.Node} payload
+ * @return {!WebInspector.DOMNode}
+ */
+ static create(domModel, doc, isInShadowTree, payload) {
var node = new WebInspector.DOMNode(domModel);
node._init(doc, isInShadowTree, payload);
return node;
-}
-
-/**
- * @enum {string}
- */
-WebInspector.DOMNode.PseudoElementNames = {
- Before: "before",
- After: "after"
-};
-
-/**
- * @enum {string}
- */
-WebInspector.DOMNode.ShadowRootTypes = {
- UserAgent: "user-agent",
- Open: "open",
- Closed: "closed"
-};
-
-/** @typedef {{name: string, value: string, _node: WebInspector.DOMNode}} */
-WebInspector.DOMNode.Attribute;
+ }
+
+ /**
+ * @param {?WebInspector.DOMDocument} doc
+ * @param {boolean} isInShadowTree
+ * @param {!DOMAgent.Node} payload
+ */
+ _init(doc, isInShadowTree, payload) {
+ this._agent = this._domModel._agent;
+ this.ownerDocument = doc;
+ this._isInShadowTree = isInShadowTree;
+
+ this.id = payload.nodeId;
+ this._domModel._idToDOMNode[this.id] = this;
+ this._nodeType = payload.nodeType;
+ this._nodeName = payload.nodeName;
+ this._localName = payload.localName;
+ this._nodeValue = payload.nodeValue;
+ this._pseudoType = payload.pseudoType;
+ this._shadowRootType = payload.shadowRootType;
+ this._frameOwnerFrameId = payload.frameId || null;
+ this._xmlVersion = payload.xmlVersion;
+
+ this._shadowRoots = [];
+
+ this._attributes = [];
+ this._attributesMap = {};
+ if (payload.attributes)
+ this._setAttributesPayload(payload.attributes);
+
+ /** @type {!Map<string, ?>} */
+ this._markers = new Map();
+ this._subtreeMarkerCount = 0;
+
+ this._childNodeCount = payload.childNodeCount || 0;
+ this._children = null;
+
+ this.nextSibling = null;
+ this.previousSibling = null;
+ this.firstChild = null;
+ this.lastChild = null;
+ this.parentNode = null;
+
+ if (payload.shadowRoots) {
+ for (var i = 0; i < payload.shadowRoots.length; ++i) {
+ var root = payload.shadowRoots[i];
+ var node = WebInspector.DOMNode.create(this._domModel, this.ownerDocument, true, root);
+ this._shadowRoots.push(node);
+ node.parentNode = this;
+ }
+ }
-WebInspector.DOMNode.prototype = {
- /**
- * @param {?WebInspector.DOMDocument} doc
- * @param {boolean} isInShadowTree
- * @param {!DOMAgent.Node} payload
- */
- _init: function(doc, isInShadowTree, payload)
- {
- this._agent = this._domModel._agent;
- this.ownerDocument = doc;
- this._isInShadowTree = isInShadowTree;
-
- this.id = payload.nodeId;
- this._domModel._idToDOMNode[this.id] = this;
- this._nodeType = payload.nodeType;
- this._nodeName = payload.nodeName;
- this._localName = payload.localName;
- this._nodeValue = payload.nodeValue;
- this._pseudoType = payload.pseudoType;
- this._shadowRootType = payload.shadowRootType;
- this._frameOwnerFrameId = payload.frameId || null;
- this._xmlVersion = payload.xmlVersion;
-
- this._shadowRoots = [];
-
- this._attributes = [];
- this._attributesMap = {};
- if (payload.attributes)
- this._setAttributesPayload(payload.attributes);
-
- /** @type {!Map<string, ?>} */
- this._markers = new Map();
- this._subtreeMarkerCount = 0;
-
- this._childNodeCount = payload.childNodeCount || 0;
- this._children = null;
-
- this.nextSibling = null;
- this.previousSibling = null;
- this.firstChild = null;
- this.lastChild = null;
- this.parentNode = null;
-
- if (payload.shadowRoots) {
- for (var i = 0; i < payload.shadowRoots.length; ++i) {
- var root = payload.shadowRoots[i];
- var node = WebInspector.DOMNode.create(this._domModel, this.ownerDocument, true, root);
- this._shadowRoots.push(node);
- node.parentNode = this;
- }
- }
+ if (payload.templateContent) {
+ this._templateContent =
+ WebInspector.DOMNode.create(this._domModel, this.ownerDocument, true, payload.templateContent);
+ this._templateContent.parentNode = this;
+ }
- if (payload.templateContent) {
- this._templateContent = WebInspector.DOMNode.create(this._domModel, this.ownerDocument, true, payload.templateContent);
- this._templateContent.parentNode = this;
- }
+ if (payload.importedDocument) {
+ this._importedDocument =
+ WebInspector.DOMNode.create(this._domModel, this.ownerDocument, true, payload.importedDocument);
+ this._importedDocument.parentNode = this;
+ }
- if (payload.importedDocument) {
- this._importedDocument = WebInspector.DOMNode.create(this._domModel, this.ownerDocument, true, payload.importedDocument);
- this._importedDocument.parentNode = this;
- }
+ if (payload.distributedNodes)
+ this._setDistributedNodePayloads(payload.distributedNodes);
- if (payload.distributedNodes)
- this._setDistributedNodePayloads(payload.distributedNodes);
+ if (payload.children)
+ this._setChildrenPayload(payload.children);
- if (payload.children)
- this._setChildrenPayload(payload.children);
+ this._setPseudoElements(payload.pseudoElements);
- this._setPseudoElements(payload.pseudoElements);
+ if (payload.contentDocument) {
+ this._contentDocument = new WebInspector.DOMDocument(this._domModel, payload.contentDocument);
+ this._children = [this._contentDocument];
+ this._renumber();
+ }
- if (payload.contentDocument) {
- this._contentDocument = new WebInspector.DOMDocument(this._domModel, payload.contentDocument);
- this._children = [this._contentDocument];
- this._renumber();
+ if (this._nodeType === Node.ELEMENT_NODE) {
+ // HTML and BODY from internal iframes should not overwrite top-level ones.
+ if (this.ownerDocument && !this.ownerDocument.documentElement && this._nodeName === 'HTML')
+ this.ownerDocument.documentElement = this;
+ if (this.ownerDocument && !this.ownerDocument.body && this._nodeName === 'BODY')
+ this.ownerDocument.body = this;
+ } else if (this._nodeType === Node.DOCUMENT_TYPE_NODE) {
+ this.publicId = payload.publicId;
+ this.systemId = payload.systemId;
+ this.internalSubset = payload.internalSubset;
+ } else if (this._nodeType === Node.ATTRIBUTE_NODE) {
+ this.name = payload.name;
+ this.value = payload.value;
+ }
+ }
+
+ /**
+ * @return {!WebInspector.DOMModel}
+ */
+ domModel() {
+ return this._domModel;
+ }
+
+ /**
+ * @return {?Array.<!WebInspector.DOMNode>}
+ */
+ children() {
+ return this._children ? this._children.slice() : null;
+ }
+
+ /**
+ * @return {boolean}
+ */
+ hasAttributes() {
+ return this._attributes.length > 0;
+ }
+
+ /**
+ * @return {number}
+ */
+ childNodeCount() {
+ return this._childNodeCount;
+ }
+
+ /**
+ * @return {boolean}
+ */
+ hasShadowRoots() {
+ return !!this._shadowRoots.length;
+ }
+
+ /**
+ * @return {!Array.<!WebInspector.DOMNode>}
+ */
+ shadowRoots() {
+ return this._shadowRoots.slice();
+ }
+
+ /**
+ * @return {?WebInspector.DOMNode}
+ */
+ templateContent() {
+ return this._templateContent || null;
+ }
+
+ /**
+ * @return {?WebInspector.DOMNode}
+ */
+ importedDocument() {
+ return this._importedDocument || null;
+ }
+
+ /**
+ * @return {number}
+ */
+ nodeType() {
+ return this._nodeType;
+ }
+
+ /**
+ * @return {string}
+ */
+ nodeName() {
+ return this._nodeName;
+ }
+
+ /**
+ * @return {string|undefined}
+ */
+ pseudoType() {
+ return this._pseudoType;
+ }
+
+ /**
+ * @return {boolean}
+ */
+ hasPseudoElements() {
+ return this._pseudoElements.size > 0;
+ }
+
+ /**
+ * @return {!Map<string, !WebInspector.DOMNode>}
+ */
+ pseudoElements() {
+ return this._pseudoElements;
+ }
+
+ /**
+ * @return {?WebInspector.DOMNode}
+ */
+ beforePseudoElement() {
+ if (!this._pseudoElements)
+ return null;
+ return this._pseudoElements.get(WebInspector.DOMNode.PseudoElementNames.Before);
+ }
+
+ /**
+ * @return {?WebInspector.DOMNode}
+ */
+ afterPseudoElement() {
+ if (!this._pseudoElements)
+ return null;
+ return this._pseudoElements.get(WebInspector.DOMNode.PseudoElementNames.After);
+ }
+
+ /**
+ * @return {boolean}
+ */
+ isInsertionPoint() {
+ return !this.isXMLNode() &&
+ (this._nodeName === 'SHADOW' || this._nodeName === 'CONTENT' || this._nodeName === 'SLOT');
+ }
+
+ /**
+ * @return {!Array.<!WebInspector.DOMNodeShortcut>}
+ */
+ distributedNodes() {
+ return this._distributedNodes || [];
+ }
+
+ /**
+ * @return {boolean}
+ */
+ isInShadowTree() {
+ return this._isInShadowTree;
+ }
+
+ /**
+ * @return {?WebInspector.DOMNode}
+ */
+ ancestorShadowHost() {
+ var ancestorShadowRoot = this.ancestorShadowRoot();
+ return ancestorShadowRoot ? ancestorShadowRoot.parentNode : null;
+ }
+
+ /**
+ * @return {?WebInspector.DOMNode}
+ */
+ ancestorShadowRoot() {
+ if (!this._isInShadowTree)
+ return null;
+
+ var current = this;
+ while (current && !current.isShadowRoot())
+ current = current.parentNode;
+ return current;
+ }
+
+ /**
+ * @return {?WebInspector.DOMNode}
+ */
+ ancestorUserAgentShadowRoot() {
+ var ancestorShadowRoot = this.ancestorShadowRoot();
+ if (!ancestorShadowRoot)
+ return null;
+ return ancestorShadowRoot.shadowRootType() === WebInspector.DOMNode.ShadowRootTypes.UserAgent ? ancestorShadowRoot :
+ null;
+ }
+
+ /**
+ * @return {boolean}
+ */
+ isShadowRoot() {
+ return !!this._shadowRootType;
+ }
+
+ /**
+ * @return {?string}
+ */
+ shadowRootType() {
+ return this._shadowRootType || null;
+ }
+
+ /**
+ * @return {string}
+ */
+ nodeNameInCorrectCase() {
+ var shadowRootType = this.shadowRootType();
+ if (shadowRootType)
+ return '#shadow-root (' + shadowRootType + ')';
+
+ // If there is no local name, it's case sensitive
+ if (!this.localName())
+ return this.nodeName();
+
+ // If the names are different lengths, there is a prefix and it's case sensitive
+ if (this.localName().length !== this.nodeName().length)
+ return this.nodeName();
+
+ // Return the localname, which will be case insensitive if its an html node
+ return this.localName();
+ }
+
+ /**
+ * @param {string} name
+ * @param {function(?Protocol.Error, number)=} callback
+ */
+ setNodeName(name, callback) {
+ this._agent.setNodeName(this.id, name, this._domModel._markRevision(this, callback));
+ }
+
+ /**
+ * @return {string}
+ */
+ localName() {
+ return this._localName;
+ }
+
+ /**
+ * @return {string}
+ */
+ nodeValue() {
+ return this._nodeValue;
+ }
+
+ /**
+ * @param {string} value
+ * @param {function(?Protocol.Error)=} callback
+ */
+ setNodeValue(value, callback) {
+ this._agent.setNodeValue(this.id, value, this._domModel._markRevision(this, callback));
+ }
+
+ /**
+ * @param {string} name
+ * @return {string}
+ */
+ getAttribute(name) {
+ var attr = this._attributesMap[name];
+ return attr ? attr.value : undefined;
+ }
+
+ /**
+ * @param {string} name
+ * @param {string} text
+ * @param {function(?Protocol.Error)=} callback
+ */
+ setAttribute(name, text, callback) {
+ this._agent.setAttributesAsText(this.id, text, name, this._domModel._markRevision(this, callback));
+ }
+
+ /**
+ * @param {string} name
+ * @param {string} value
+ * @param {function(?Protocol.Error)=} callback
+ */
+ setAttributeValue(name, value, callback) {
+ this._agent.setAttributeValue(this.id, name, value, this._domModel._markRevision(this, callback));
+ }
+
+ /**
+ * @return {!Array<!WebInspector.DOMNode.Attribute>}
+ */
+ attributes() {
+ return this._attributes;
+ }
+
+ /**
+ * @param {string} name
+ * @param {function(?Protocol.Error)=} callback
+ */
+ removeAttribute(name, callback) {
+ /**
+ * @param {?Protocol.Error} error
+ * @this {WebInspector.DOMNode}
+ */
+ function mycallback(error) {
+ if (!error) {
+ delete this._attributesMap[name];
+ for (var i = 0; i < this._attributes.length; ++i) {
+ if (this._attributes[i].name === name) {
+ this._attributes.splice(i, 1);
+ break;
+ }
}
+ }
- if (this._nodeType === Node.ELEMENT_NODE) {
- // HTML and BODY from internal iframes should not overwrite top-level ones.
- if (this.ownerDocument && !this.ownerDocument.documentElement && this._nodeName === "HTML")
- this.ownerDocument.documentElement = this;
- if (this.ownerDocument && !this.ownerDocument.body && this._nodeName === "BODY")
- this.ownerDocument.body = this;
- } else if (this._nodeType === Node.DOCUMENT_TYPE_NODE) {
- this.publicId = payload.publicId;
- this.systemId = payload.systemId;
- this.internalSubset = payload.internalSubset;
- } else if (this._nodeType === Node.ATTRIBUTE_NODE) {
- this.name = payload.name;
- this.value = payload.value;
- }
- },
+ this._domModel._markRevision(this, callback)(error);
+ }
+ this._agent.removeAttribute(this.id, name, mycallback.bind(this));
+ }
+
+ /**
+ * @param {function(?Array.<!WebInspector.DOMNode>)=} callback
+ */
+ getChildNodes(callback) {
+ if (this._children) {
+ if (callback)
+ callback(this.children());
+ return;
+ }
/**
- * @return {!WebInspector.DOMModel}
+ * @this {WebInspector.DOMNode}
+ * @param {?Protocol.Error} error
*/
- domModel: function()
- {
- return this._domModel;
- },
+ function mycallback(error) {
+ if (callback)
+ callback(error ? null : this.children());
+ }
- /**
- * @return {?Array.<!WebInspector.DOMNode>}
- */
- children: function()
- {
- return this._children ? this._children.slice() : null;
- },
+ this._agent.requestChildNodes(this.id, undefined, mycallback.bind(this));
+ }
+ /**
+ * @param {number} depth
+ * @param {function(?Array.<!WebInspector.DOMNode>)=} callback
+ */
+ getSubtree(depth, callback) {
/**
- * @return {boolean}
+ * @this {WebInspector.DOMNode}
+ * @param {?Protocol.Error} error
*/
- hasAttributes: function()
- {
- return this._attributes.length > 0;
- },
+ function mycallback(error) {
+ if (callback)
+ callback(error ? null : this._children);
+ }
- /**
- * @return {number}
- */
- childNodeCount: function()
- {
- return this._childNodeCount;
- },
+ this._agent.requestChildNodes(this.id, depth, mycallback.bind(this));
+ }
+
+ /**
+ * @param {function(?Protocol.Error, string)=} callback
+ */
+ getOuterHTML(callback) {
+ this._agent.getOuterHTML(this.id, callback);
+ }
+
+ /**
+ * @param {string} html
+ * @param {function(?Protocol.Error)=} callback
+ */
+ setOuterHTML(html, callback) {
+ this._agent.setOuterHTML(this.id, html, this._domModel._markRevision(this, callback));
+ }
+
+ /**
+ * @param {function(?Protocol.Error, !DOMAgent.NodeId=)=} callback
+ */
+ removeNode(callback) {
+ this._agent.removeNode(this.id, this._domModel._markRevision(this, callback));
+ }
+
+ /**
+ * @param {function(?string)=} callback
+ */
+ copyNode(callback) {
+ function copy(error, text) {
+ if (!error)
+ InspectorFrontendHost.copyText(text);
+ if (callback)
+ callback(error ? null : text);
+ }
+ this._agent.getOuterHTML(this.id, copy);
+ }
+ /**
+ * @return {string}
+ */
+ path() {
/**
- * @return {boolean}
+ * @param {?WebInspector.DOMNode} node
*/
- hasShadowRoots: function()
- {
- return !!this._shadowRoots.length;
- },
+ function canPush(node) {
+ return node && ('index' in node || (node.isShadowRoot() && node.parentNode)) && node._nodeName.length;
+ }
- /**
- * @return {!Array.<!WebInspector.DOMNode>}
- */
- shadowRoots: function()
- {
- return this._shadowRoots.slice();
- },
+ var path = [];
+ var node = this;
+ while (canPush(node)) {
+ var index = typeof node.index === 'number' ?
+ node.index :
+ (node.shadowRootType() === WebInspector.DOMNode.ShadowRootTypes.UserAgent ? 'u' : 'a');
+ path.push([index, node._nodeName]);
+ node = node.parentNode;
+ }
+ path.reverse();
+ return path.join(',');
+ }
+
+ /**
+ * @param {!WebInspector.DOMNode} node
+ * @return {boolean}
+ */
+ isAncestor(node) {
+ if (!node)
+ return false;
+
+ var currentNode = node.parentNode;
+ while (currentNode) {
+ if (this === currentNode)
+ return true;
+ currentNode = currentNode.parentNode;
+ }
+ return false;
+ }
+
+ /**
+ * @param {!WebInspector.DOMNode} descendant
+ * @return {boolean}
+ */
+ isDescendant(descendant) {
+ return descendant !== null && descendant.isAncestor(this);
+ }
+
+ /**
+ * @return {?PageAgent.FrameId}
+ */
+ frameId() {
+ var node = this.parentNode || this;
+ while (!node._frameOwnerFrameId && node.parentNode)
+ node = node.parentNode;
+ return node._frameOwnerFrameId;
+ }
+
+ /**
+ * @param {!Array.<string>} attrs
+ * @return {boolean}
+ */
+ _setAttributesPayload(attrs) {
+ var attributesChanged = !this._attributes || attrs.length !== this._attributes.length * 2;
+ var oldAttributesMap = this._attributesMap || {};
+
+ this._attributes = [];
+ this._attributesMap = {};
+
+ for (var i = 0; i < attrs.length; i += 2) {
+ var name = attrs[i];
+ var value = attrs[i + 1];
+ this._addAttribute(name, value);
+
+ if (attributesChanged)
+ continue;
+
+ if (!oldAttributesMap[name] || oldAttributesMap[name].value !== value)
+ attributesChanged = true;
+ }
+ return attributesChanged;
+ }
+
+ /**
+ * @param {!WebInspector.DOMNode} prev
+ * @param {!DOMAgent.Node} payload
+ * @return {!WebInspector.DOMNode}
+ */
+ _insertChild(prev, payload) {
+ var node = WebInspector.DOMNode.create(this._domModel, this.ownerDocument, this._isInShadowTree, payload);
+ this._children.splice(this._children.indexOf(prev) + 1, 0, node);
+ this._renumber();
+ return node;
+ }
+
+ /**
+ * @param {!WebInspector.DOMNode} node
+ */
+ _removeChild(node) {
+ if (node.pseudoType()) {
+ this._pseudoElements.delete(node.pseudoType());
+ } else {
+ var shadowRootIndex = this._shadowRoots.indexOf(node);
+ if (shadowRootIndex !== -1) {
+ this._shadowRoots.splice(shadowRootIndex, 1);
+ } else {
+ console.assert(this._children.indexOf(node) !== -1);
+ this._children.splice(this._children.indexOf(node), 1);
+ }
+ }
+ node.parentNode = null;
+ this._subtreeMarkerCount -= node._subtreeMarkerCount;
+ if (node._subtreeMarkerCount)
+ this._domModel.dispatchEventToListeners(WebInspector.DOMModel.Events.MarkersChanged, this);
+ this._renumber();
+ }
+
+ /**
+ * @param {!Array.<!DOMAgent.Node>} payloads
+ */
+ _setChildrenPayload(payloads) {
+ // We set children in the constructor.
+ if (this._contentDocument)
+ return;
+
+ this._children = [];
+ for (var i = 0; i < payloads.length; ++i) {
+ var payload = payloads[i];
+ var node = WebInspector.DOMNode.create(this._domModel, this.ownerDocument, this._isInShadowTree, payload);
+ this._children.push(node);
+ }
+ this._renumber();
+ }
+
+ /**
+ * @param {!Array.<!DOMAgent.Node>|undefined} payloads
+ */
+ _setPseudoElements(payloads) {
+ this._pseudoElements = new Map();
+ if (!payloads)
+ return;
+
+ for (var i = 0; i < payloads.length; ++i) {
+ var node = WebInspector.DOMNode.create(this._domModel, this.ownerDocument, this._isInShadowTree, payloads[i]);
+ node.parentNode = this;
+ this._pseudoElements.set(node.pseudoType(), node);
+ }
+ }
+
+ /**
+ * @param {!Array.<!DOMAgent.BackendNode>} payloads
+ */
+ _setDistributedNodePayloads(payloads) {
+ this._distributedNodes = [];
+ for (var payload of payloads)
+ this._distributedNodes.push(new WebInspector.DOMNodeShortcut(
+ this._domModel.target(), payload.backendNodeId, payload.nodeType, payload.nodeName));
+ }
+
+ _renumber() {
+ this._childNodeCount = this._children.length;
+ if (this._childNodeCount === 0) {
+ this.firstChild = null;
+ this.lastChild = null;
+ return;
+ }
+ this.firstChild = this._children[0];
+ this.lastChild = this._children[this._childNodeCount - 1];
+ for (var i = 0; i < this._childNodeCount; ++i) {
+ var child = this._children[i];
+ child.index = i;
+ child.nextSibling = i + 1 < this._childNodeCount ? this._children[i + 1] : null;
+ child.previousSibling = i - 1 >= 0 ? this._children[i - 1] : null;
+ child.parentNode = this;
+ }
+ }
+
+ /**
+ * @param {string} name
+ * @param {string} value
+ */
+ _addAttribute(name, value) {
+ var attr = {name: name, value: value, _node: this};
+ this._attributesMap[name] = attr;
+ this._attributes.push(attr);
+ }
+
+ /**
+ * @param {string} name
+ * @param {string} value
+ */
+ _setAttribute(name, value) {
+ var attr = this._attributesMap[name];
+ if (attr)
+ attr.value = value;
+ else
+ this._addAttribute(name, value);
+ }
+
+ /**
+ * @param {string} name
+ */
+ _removeAttribute(name) {
+ var attr = this._attributesMap[name];
+ if (attr) {
+ this._attributes.remove(attr);
+ delete this._attributesMap[name];
+ }
+ }
+
+ /**
+ * @param {!WebInspector.DOMNode} targetNode
+ * @param {?WebInspector.DOMNode} anchorNode
+ * @param {function(?Protocol.Error, !DOMAgent.NodeId=)=} callback
+ */
+ copyTo(targetNode, anchorNode, callback) {
+ this._agent.copyTo(
+ this.id, targetNode.id, anchorNode ? anchorNode.id : undefined, this._domModel._markRevision(this, callback));
+ }
+
+ /**
+ * @param {!WebInspector.DOMNode} targetNode
+ * @param {?WebInspector.DOMNode} anchorNode
+ * @param {function(?Protocol.Error, !DOMAgent.NodeId=)=} callback
+ */
+ moveTo(targetNode, anchorNode, callback) {
+ this._agent.moveTo(
+ this.id, targetNode.id, anchorNode ? anchorNode.id : undefined, this._domModel._markRevision(this, callback));
+ }
+
+ /**
+ * @return {boolean}
+ */
+ isXMLNode() {
+ return !!this._xmlVersion;
+ }
+
+ /**
+ * @param {string} name
+ * @param {?*} value
+ */
+ setMarker(name, value) {
+ if (value === null) {
+ if (!this._markers.has(name))
+ return;
+
+ this._markers.delete(name);
+ for (var node = this; node; node = node.parentNode)
+ --node._subtreeMarkerCount;
+ for (var node = this; node; node = node.parentNode)
+ this._domModel.dispatchEventToListeners(WebInspector.DOMModel.Events.MarkersChanged, node);
+ return;
+ }
+ if (this.parentNode && !this._markers.has(name)) {
+ for (var node = this; node; node = node.parentNode)
+ ++node._subtreeMarkerCount;
+ }
+ this._markers.set(name, value);
+ for (var node = this; node; node = node.parentNode)
+ this._domModel.dispatchEventToListeners(WebInspector.DOMModel.Events.MarkersChanged, node);
+ }
+
+ /**
+ * @param {string} name
+ * @return {?T}
+ * @template T
+ */
+ marker(name) {
+ return this._markers.get(name) || null;
+ }
+
+ /**
+ * @param {function(!WebInspector.DOMNode, string)} visitor
+ */
+ traverseMarkers(visitor) {
/**
- * @return {?WebInspector.DOMNode}
+ * @param {!WebInspector.DOMNode} node
*/
- templateContent: function()
- {
- return this._templateContent || null;
- },
+ function traverse(node) {
+ if (!node._subtreeMarkerCount)
+ return;
+ for (var marker of node._markers.keys())
+ visitor(node, marker);
+ if (!node._children)
+ return;
+ for (var child of node._children)
+ traverse(child);
+ }
+ traverse(this);
+ }
+
+ /**
+ * @param {string} url
+ * @return {?string}
+ */
+ resolveURL(url) {
+ if (!url)
+ return url;
+ for (var frameOwnerCandidate = this; frameOwnerCandidate; frameOwnerCandidate = frameOwnerCandidate.parentNode) {
+ if (frameOwnerCandidate.baseURL)
+ return WebInspector.ParsedURL.completeURL(frameOwnerCandidate.baseURL, url);
+ }
+ return null;
+ }
+
+ /**
+ * @param {string=} mode
+ * @param {!RuntimeAgent.RemoteObjectId=} objectId
+ */
+ highlight(mode, objectId) {
+ this._domModel.highlightDOMNode(this.id, mode, undefined, objectId);
+ }
+
+ highlightForTwoSeconds() {
+ this._domModel.highlightDOMNodeForTwoSeconds(this.id);
+ }
+
+ /**
+ * @param {string=} objectGroup
+ * @param {function(?WebInspector.RemoteObject)=} callback
+ */
+ resolveToObject(objectGroup, callback) {
+ this._agent.resolveNode(this.id, objectGroup, mycallback.bind(this));
+
+ /**
+ * @param {?Protocol.Error} error
+ * @param {!RuntimeAgent.RemoteObject} object
+ * @this {WebInspector.DOMNode}
+ */
+ function mycallback(error, object) {
+ if (!callback)
+ return;
+
+ if (error || !object)
+ callback(null);
+ else
+ callback(this.target().runtimeModel.createRemoteObject(object));
+ }
+ }
+
+ /**
+ * @param {string=} objectGroup
+ * @return {!Promise<!WebInspector.RemoteObject>}
+ */
+ resolveToObjectPromise(objectGroup) {
+ return new Promise(resolveToObject.bind(this));
+ /**
+ * @param {function(?)} fulfill
+ * @param {function(*)} reject
+ * @this {WebInspector.DOMNode}
+ */
+ function resolveToObject(fulfill, reject) {
+ this.resolveToObject(objectGroup, mycallback);
+ function mycallback(object) {
+ if (object)
+ fulfill(object);
+ else
+ reject(null);
+ }
+ }
+ }
+
+ /**
+ * @param {function(?DOMAgent.BoxModel)} callback
+ */
+ boxModel(callback) {
+ this._agent.getBoxModel(this.id, this._domModel._wrapClientCallback(callback));
+ }
+
+ setAsInspectedNode() {
+ var node = this;
+ while (true) {
+ var ancestor = node.ancestorUserAgentShadowRoot();
+ if (!ancestor)
+ break;
+ ancestor = node.ancestorShadowHost();
+ if (!ancestor)
+ break;
+ // User agent shadow root, keep climbing up.
+ node = ancestor;
+ }
+ this._agent.setInspectedNode(node.id);
+ }
+
+ /**
+ * @return {?WebInspector.DOMNode}
+ */
+ enclosingElementOrSelf() {
+ var node = this;
+ if (node && node.nodeType() === Node.TEXT_NODE && node.parentNode)
+ node = node.parentNode;
+
+ if (node && node.nodeType() !== Node.ELEMENT_NODE)
+ node = null;
+ return node;
+ }
+};
- /**
- * @return {?WebInspector.DOMNode}
- */
- importedDocument: function()
- {
- return this._importedDocument || null;
- },
+/**
+ * @enum {string}
+ */
+WebInspector.DOMNode.PseudoElementNames = {
+ Before: 'before',
+ After: 'after'
+};
- /**
- * @return {number}
- */
- nodeType: function()
- {
- return this._nodeType;
- },
+/**
+ * @enum {string}
+ */
+WebInspector.DOMNode.ShadowRootTypes = {
+ UserAgent: 'user-agent',
+ Open: 'open',
+ Closed: 'closed'
+};
- /**
- * @return {string}
- */
- nodeName: function()
- {
- return this._nodeName;
- },
+/** @typedef {{name: string, value: string, _node: WebInspector.DOMNode}} */
+WebInspector.DOMNode.Attribute;
- /**
- * @return {string|undefined}
- */
- pseudoType: function()
- {
- return this._pseudoType;
- },
+/**
+ * @unrestricted
+ */
+WebInspector.DeferredDOMNode = class {
+ /**
+ * @param {!WebInspector.Target} target
+ * @param {number} backendNodeId
+ */
+ constructor(target, backendNodeId) {
+ this._domModel = WebInspector.DOMModel.fromTarget(target);
+ this._backendNodeId = backendNodeId;
+ }
+
+ /**
+ * @param {function(?WebInspector.DOMNode)} callback
+ */
+ resolve(callback) {
+ if (!this._domModel) {
+ callback(null);
+ return;
+ }
- /**
- * @return {boolean}
- */
- hasPseudoElements: function()
- {
- return this._pseudoElements.size > 0;
- },
+ this._domModel.pushNodesByBackendIdsToFrontend(new Set([this._backendNodeId]), onGotNode.bind(this));
/**
- * @return {!Map<string, !WebInspector.DOMNode>}
+ * @param {?Map<number, ?WebInspector.DOMNode>} nodeIds
+ * @this {WebInspector.DeferredDOMNode}
*/
- pseudoElements: function()
- {
- return this._pseudoElements;
- },
+ function onGotNode(nodeIds) {
+ callback(nodeIds && (nodeIds.get(this._backendNodeId) || null));
+ }
+ }
+
+ /**
+ * @return {!Promise.<!WebInspector.DOMNode>}
+ */
+ resolvePromise() {
+ /**
+ * @param {function(?)} fulfill
+ * @param {function(*)} reject
+ * @this {WebInspector.DeferredDOMNode}
+ */
+ function resolveNode(fulfill, reject) {
+ /**
+ * @param {?WebInspector.DOMNode} node
+ */
+ function mycallback(node) {
+ fulfill(node);
+ }
+ this.resolve(mycallback);
+ }
+ return new Promise(resolveNode.bind(this));
+ }
+
+ /**
+ * @return {number}
+ */
+ backendNodeId() {
+ return this._backendNodeId;
+ }
+
+ highlight() {
+ if (this._domModel)
+ this._domModel.highlightDOMNode(undefined, undefined, this._backendNodeId);
+ }
+};
- /**
- * @return {?WebInspector.DOMNode}
- */
- beforePseudoElement: function()
- {
- if (!this._pseudoElements)
- return null;
- return this._pseudoElements.get(WebInspector.DOMNode.PseudoElementNames.Before);
- },
+/**
+ * @unrestricted
+ */
+WebInspector.DOMNodeShortcut = class {
+ /**
+ * @param {!WebInspector.Target} target
+ * @param {number} backendNodeId
+ * @param {number} nodeType
+ * @param {string} nodeName
+ */
+ constructor(target, backendNodeId, nodeType, nodeName) {
+ this.nodeType = nodeType;
+ this.nodeName = nodeName;
+ this.deferredNode = new WebInspector.DeferredDOMNode(target, backendNodeId);
+ }
+};
- /**
- * @return {?WebInspector.DOMNode}
- */
- afterPseudoElement: function()
- {
- if (!this._pseudoElements)
- return null;
- return this._pseudoElements.get(WebInspector.DOMNode.PseudoElementNames.After);
- },
+/**
+ * @unrestricted
+ */
+WebInspector.DOMDocument = class extends WebInspector.DOMNode {
+ /**
+ * @param {!WebInspector.DOMModel} domModel
+ * @param {!DOMAgent.Node} payload
+ */
+ constructor(domModel, payload) {
+ super(domModel);
+ this._init(this, false, payload);
+ this.documentURL = payload.documentURL || '';
+ this.baseURL = payload.baseURL || '';
+ this._listeners = {};
+ }
+};
- /**
- * @return {boolean}
- */
- isInsertionPoint: function()
- {
- return !this.isXMLNode() && (this._nodeName === "SHADOW" || this._nodeName === "CONTENT" || this._nodeName === "SLOT");
- },
+/**
+ * @unrestricted
+ */
+WebInspector.DOMModel = class extends WebInspector.SDKModel {
+ /**
+ * @param {!WebInspector.Target} target
+ */
+ constructor(target) {
+ super(WebInspector.DOMModel, target);
- /**
- * @return {!Array.<!WebInspector.DOMNodeShortcut>}
- */
- distributedNodes: function()
- {
- return this._distributedNodes || [];
- },
+ this._agent = target.domAgent();
- /**
- * @return {boolean}
- */
- isInShadowTree: function()
- {
- return this._isInShadowTree;
- },
+ /** @type {!Object.<number, !WebInspector.DOMNode>} */
+ this._idToDOMNode = {};
+ /** @type {?WebInspector.DOMDocument} */
+ this._document = null;
+ /** @type {!Object.<number, boolean>} */
+ this._attributeLoadNodeIds = {};
+ target.registerDOMDispatcher(new WebInspector.DOMDispatcher(this));
- /**
- * @return {?WebInspector.DOMNode}
- */
- ancestorShadowHost: function()
- {
- var ancestorShadowRoot = this.ancestorShadowRoot();
- return ancestorShadowRoot ? ancestorShadowRoot.parentNode : null;
- },
+ this._inspectModeEnabled = false;
- /**
- * @return {?WebInspector.DOMNode}
- */
- ancestorShadowRoot: function()
- {
- if (!this._isInShadowTree)
- return null;
+ this._defaultHighlighter = new WebInspector.DefaultDOMNodeHighlighter(this._agent);
+ this._highlighter = this._defaultHighlighter;
- var current = this;
- while (current && !current.isShadowRoot())
- current = current.parentNode;
- return current;
- },
+ this._agent.enable();
+ }
- /**
- * @return {?WebInspector.DOMNode}
- */
- ancestorUserAgentShadowRoot: function()
- {
- var ancestorShadowRoot = this.ancestorShadowRoot();
- if (!ancestorShadowRoot)
- return null;
- return ancestorShadowRoot.shadowRootType() === WebInspector.DOMNode.ShadowRootTypes.UserAgent ? ancestorShadowRoot : null;
- },
+ /**
+ * @param {!WebInspector.RemoteObject} object
+ */
+ static highlightObjectAsDOMNode(object) {
+ var domModel = WebInspector.DOMModel.fromTarget(object.target());
+ if (domModel)
+ domModel.highlightDOMNode(undefined, undefined, undefined, object.objectId);
+ }
- /**
- * @return {boolean}
- */
- isShadowRoot: function()
- {
- return !!this._shadowRootType;
- },
+ /**
+ * @return {!Array<!WebInspector.DOMModel>}
+ */
+ static instances() {
+ var result = [];
+ for (var target of WebInspector.targetManager.targets()) {
+ var domModel = WebInspector.DOMModel.fromTarget(target);
+ if (domModel)
+ result.push(domModel);
+ }
+ return result;
+ }
- /**
- * @return {?string}
- */
- shadowRootType: function()
- {
- return this._shadowRootType || null;
- },
+ static hideDOMNodeHighlight() {
+ for (var domModel of WebInspector.DOMModel.instances())
+ domModel.highlightDOMNode(0);
+ }
- /**
- * @return {string}
- */
- nodeNameInCorrectCase: function()
- {
- var shadowRootType = this.shadowRootType();
- if (shadowRootType)
- return "#shadow-root (" + shadowRootType + ")";
+ static muteHighlight() {
+ WebInspector.DOMModel.hideDOMNodeHighlight();
+ WebInspector.DOMModel._highlightDisabled = true;
+ }
- // If there is no local name, it's case sensitive
- if (!this.localName())
- return this.nodeName();
+ static unmuteHighlight() {
+ WebInspector.DOMModel._highlightDisabled = false;
+ }
- // If the names are different lengths, there is a prefix and it's case sensitive
- if (this.localName().length !== this.nodeName().length)
- return this.nodeName();
+ static cancelSearch() {
+ for (var domModel of WebInspector.DOMModel.instances())
+ domModel._cancelSearch();
+ }
+
+ /**
+ * @param {!WebInspector.Target} target
+ * @return {?WebInspector.DOMModel}
+ */
+ static fromTarget(target) {
+ return /** @type {?WebInspector.DOMModel} */ (target.model(WebInspector.DOMModel));
+ }
- // Return the localname, which will be case insensitive if its an html node
- return this.localName();
- },
+ /**
+ * @param {!WebInspector.DOMNode} node
+ */
+ _scheduleMutationEvent(node) {
+ if (!this.hasEventListeners(WebInspector.DOMModel.Events.DOMMutated))
+ return;
- /**
- * @param {string} name
- * @param {function(?Protocol.Error, number)=} callback
- */
- setNodeName: function(name, callback)
- {
- this._agent.setNodeName(this.id, name, this._domModel._markRevision(this, callback));
- },
+ this._lastMutationId = (this._lastMutationId || 0) + 1;
+ Promise.resolve().then(callObserve.bind(this, node, this._lastMutationId));
/**
- * @return {string}
+ * @this {WebInspector.DOMModel}
+ * @param {!WebInspector.DOMNode} node
+ * @param {number} mutationId
*/
- localName: function()
- {
- return this._localName;
- },
+ function callObserve(node, mutationId) {
+ if (!this.hasEventListeners(WebInspector.DOMModel.Events.DOMMutated) || this._lastMutationId !== mutationId)
+ return;
- /**
- * @return {string}
- */
- nodeValue: function()
- {
- return this._nodeValue;
- },
+ this.dispatchEventToListeners(WebInspector.DOMModel.Events.DOMMutated, node);
+ }
+ }
+
+ /**
+ * @param {function(!WebInspector.DOMDocument)=} callback
+ */
+ requestDocument(callback) {
+ if (this._document) {
+ if (callback)
+ callback(this._document);
+ return;
+ }
- /**
- * @param {string} value
- * @param {function(?Protocol.Error)=} callback
- */
- setNodeValue: function(value, callback)
- {
- this._agent.setNodeValue(this.id, value, this._domModel._markRevision(this, callback));
- },
+ if (this._pendingDocumentRequestCallbacks) {
+ this._pendingDocumentRequestCallbacks.push(callback);
+ return;
+ }
- /**
- * @param {string} name
- * @return {string}
- */
- getAttribute: function(name)
- {
- var attr = this._attributesMap[name];
- return attr ? attr.value : undefined;
- },
+ this._pendingDocumentRequestCallbacks = [callback];
/**
- * @param {string} name
- * @param {string} text
- * @param {function(?Protocol.Error)=} callback
+ * @this {WebInspector.DOMModel}
+ * @param {?Protocol.Error} error
+ * @param {!DOMAgent.Node} root
*/
- setAttribute: function(name, text, callback)
- {
- this._agent.setAttributesAsText(this.id, text, name, this._domModel._markRevision(this, callback));
- },
+ function onDocumentAvailable(error, root) {
+ if (!error)
+ this._setDocument(root);
- /**
- * @param {string} name
- * @param {string} value
- * @param {function(?Protocol.Error)=} callback
- */
- setAttributeValue: function(name, value, callback)
- {
- this._agent.setAttributeValue(this.id, name, value, this._domModel._markRevision(this, callback));
- },
+ for (var i = 0; i < this._pendingDocumentRequestCallbacks.length; ++i) {
+ var callback = this._pendingDocumentRequestCallbacks[i];
+ if (callback)
+ callback(this._document);
+ }
+ delete this._pendingDocumentRequestCallbacks;
+ }
- /**
- * @return {!Array<!WebInspector.DOMNode.Attribute>}
- */
- attributes: function()
- {
- return this._attributes;
- },
+ this._agent.getDocument(undefined, undefined, onDocumentAvailable.bind(this));
+ }
- /**
- * @param {string} name
- * @param {function(?Protocol.Error)=} callback
- */
- removeAttribute: function(name, callback)
- {
- /**
- * @param {?Protocol.Error} error
- * @this {WebInspector.DOMNode}
- */
- function mycallback(error)
- {
- if (!error) {
- delete this._attributesMap[name];
- for (var i = 0; i < this._attributes.length; ++i) {
- if (this._attributes[i].name === name) {
- this._attributes.splice(i, 1);
- break;
- }
- }
- }
-
- this._domModel._markRevision(this, callback)(error);
- }
- this._agent.removeAttribute(this.id, name, mycallback.bind(this));
- },
+ /**
+ * @return {?WebInspector.DOMDocument}
+ */
+ existingDocument() {
+ return this._document;
+ }
+ /**
+ * @param {!RuntimeAgent.RemoteObjectId} objectId
+ * @param {function(?WebInspector.DOMNode)=} callback
+ */
+ pushNodeToFrontend(objectId, callback) {
/**
- * @param {function(?Array.<!WebInspector.DOMNode>)=} callback
+ * @param {?DOMAgent.NodeId} nodeId
+ * @this {!WebInspector.DOMModel}
+ */
+ function mycallback(nodeId) {
+ callback(nodeId ? this.nodeForId(nodeId) : null);
+ }
+ this._dispatchWhenDocumentAvailable(this._agent.requestNode.bind(this._agent, objectId), mycallback.bind(this));
+ }
+
+ /**
+ * @param {string} path
+ * @param {function(?number)=} callback
+ */
+ pushNodeByPathToFrontend(path, callback) {
+ this._dispatchWhenDocumentAvailable(this._agent.pushNodeByPathToFrontend.bind(this._agent, path), callback);
+ }
+
+ /**
+ * @param {!Set<number>} backendNodeIds
+ * @param {function(?Map<number, ?WebInspector.DOMNode>)} callback
+ */
+ pushNodesByBackendIdsToFrontend(backendNodeIds, callback) {
+ var backendNodeIdsArray = backendNodeIds.valuesArray();
+ /**
+ * @param {?Array<!DOMAgent.NodeId>} nodeIds
+ * @this {!WebInspector.DOMModel}
+ */
+ function mycallback(nodeIds) {
+ if (!nodeIds) {
+ callback(null);
+ return;
+ }
+ /** @type {!Map<number, ?WebInspector.DOMNode>} */
+ var map = new Map();
+ for (var i = 0; i < nodeIds.length; ++i) {
+ if (nodeIds[i])
+ map.set(backendNodeIdsArray[i], this.nodeForId(nodeIds[i]));
+ }
+ callback(map);
+ }
+ this._dispatchWhenDocumentAvailable(
+ this._agent.pushNodesByBackendIdsToFrontend.bind(this._agent, backendNodeIdsArray), mycallback.bind(this));
+ }
+
+ /**
+ * @param {function(!T)=} callback
+ * @return {function(?Protocol.Error, !T=)|undefined}
+ * @template T
+ */
+ _wrapClientCallback(callback) {
+ if (!callback)
+ return;
+ /**
+ * @param {?Protocol.Error} error
+ * @param {!T=} result
+ * @template T
*/
- getChildNodes: function(callback)
- {
- if (this._children) {
- if (callback)
- callback(this.children());
- return;
+ var wrapper = function(error, result) {
+ // Caller is responsible for handling the actual error.
+ callback(error ? null : result);
+ };
+ return wrapper;
+ }
+
+ /**
+ * @param {function(function(?Protocol.Error, !T=)=)} func
+ * @param {function(!T)=} callback
+ * @template T
+ */
+ _dispatchWhenDocumentAvailable(func, callback) {
+ var callbackWrapper = this._wrapClientCallback(callback);
+
+ /**
+ * @this {WebInspector.DOMModel}
+ */
+ function onDocumentAvailable() {
+ if (this._document)
+ func(callbackWrapper);
+ else {
+ if (callbackWrapper)
+ callbackWrapper('No document');
+ }
+ }
+ this.requestDocument(onDocumentAvailable.bind(this));
+ }
+
+ /**
+ * @param {!DOMAgent.NodeId} nodeId
+ * @param {string} name
+ * @param {string} value
+ */
+ _attributeModified(nodeId, name, value) {
+ var node = this._idToDOMNode[nodeId];
+ if (!node)
+ return;
+
+ node._setAttribute(name, value);
+ this.dispatchEventToListeners(WebInspector.DOMModel.Events.AttrModified, {node: node, name: name});
+ this._scheduleMutationEvent(node);
+ }
+
+ /**
+ * @param {!DOMAgent.NodeId} nodeId
+ * @param {string} name
+ */
+ _attributeRemoved(nodeId, name) {
+ var node = this._idToDOMNode[nodeId];
+ if (!node)
+ return;
+ node._removeAttribute(name);
+ this.dispatchEventToListeners(WebInspector.DOMModel.Events.AttrRemoved, {node: node, name: name});
+ this._scheduleMutationEvent(node);
+ }
+
+ /**
+ * @param {!Array.<!DOMAgent.NodeId>} nodeIds
+ */
+ _inlineStyleInvalidated(nodeIds) {
+ for (var i = 0; i < nodeIds.length; ++i)
+ this._attributeLoadNodeIds[nodeIds[i]] = true;
+ if ('_loadNodeAttributesTimeout' in this)
+ return;
+ this._loadNodeAttributesTimeout = setTimeout(this._loadNodeAttributes.bind(this), 20);
+ }
+
+ _loadNodeAttributes() {
+ /**
+ * @this {WebInspector.DOMModel}
+ * @param {!DOMAgent.NodeId} nodeId
+ * @param {?Protocol.Error} error
+ * @param {!Array.<string>} attributes
+ */
+ function callback(nodeId, error, attributes) {
+ if (error) {
+ // We are calling _loadNodeAttributes asynchronously, it is ok if node is not found.
+ return;
+ }
+ var node = this._idToDOMNode[nodeId];
+ if (node) {
+ if (node._setAttributesPayload(attributes)) {
+ this.dispatchEventToListeners(WebInspector.DOMModel.Events.AttrModified, {node: node, name: 'style'});
+ this._scheduleMutationEvent(node);
}
+ }
+ }
- /**
- * @this {WebInspector.DOMNode}
- * @param {?Protocol.Error} error
- */
- function mycallback(error)
- {
- if (callback)
- callback(error ? null : this.children());
- }
+ delete this._loadNodeAttributesTimeout;
- this._agent.requestChildNodes(this.id, undefined, mycallback.bind(this));
- },
+ for (var nodeId in this._attributeLoadNodeIds) {
+ var nodeIdAsNumber = parseInt(nodeId, 10);
+ this._agent.getAttributes(nodeIdAsNumber, callback.bind(this, nodeIdAsNumber));
+ }
+ this._attributeLoadNodeIds = {};
+ }
+
+ /**
+ * @param {!DOMAgent.NodeId} nodeId
+ * @param {string} newValue
+ */
+ _characterDataModified(nodeId, newValue) {
+ var node = this._idToDOMNode[nodeId];
+ node._nodeValue = newValue;
+ this.dispatchEventToListeners(WebInspector.DOMModel.Events.CharacterDataModified, node);
+ this._scheduleMutationEvent(node);
+ }
+
+ /**
+ * @param {!DOMAgent.NodeId} nodeId
+ * @return {?WebInspector.DOMNode}
+ */
+ nodeForId(nodeId) {
+ return this._idToDOMNode[nodeId] || null;
+ }
+
+ _documentUpdated() {
+ this._setDocument(null);
+ }
+
+ /**
+ * @param {?DOMAgent.Node} payload
+ */
+ _setDocument(payload) {
+ this._idToDOMNode = {};
+ if (payload && 'nodeId' in payload)
+ this._document = new WebInspector.DOMDocument(this, payload);
+ else
+ this._document = null;
+ this.dispatchEventToListeners(WebInspector.DOMModel.Events.DocumentUpdated, this._document);
+ }
+
+ /**
+ * @param {!DOMAgent.Node} payload
+ */
+ _setDetachedRoot(payload) {
+ if (payload.nodeName === '#document')
+ new WebInspector.DOMDocument(this, payload);
+ else
+ WebInspector.DOMNode.create(this, null, false, payload);
+ }
+
+ /**
+ * @param {!DOMAgent.NodeId} parentId
+ * @param {!Array.<!DOMAgent.Node>} payloads
+ */
+ _setChildNodes(parentId, payloads) {
+ if (!parentId && payloads.length) {
+ this._setDetachedRoot(payloads[0]);
+ return;
+ }
- /**
- * @param {number} depth
- * @param {function(?Array.<!WebInspector.DOMNode>)=} callback
- */
- getSubtree: function(depth, callback)
- {
- /**
- * @this {WebInspector.DOMNode}
- * @param {?Protocol.Error} error
- */
- function mycallback(error)
- {
- if (callback)
- callback(error ? null : this._children);
- }
+ var parent = this._idToDOMNode[parentId];
+ parent._setChildrenPayload(payloads);
+ }
+
+ /**
+ * @param {!DOMAgent.NodeId} nodeId
+ * @param {number} newValue
+ */
+ _childNodeCountUpdated(nodeId, newValue) {
+ var node = this._idToDOMNode[nodeId];
+ node._childNodeCount = newValue;
+ this.dispatchEventToListeners(WebInspector.DOMModel.Events.ChildNodeCountUpdated, node);
+ this._scheduleMutationEvent(node);
+ }
+
+ /**
+ * @param {!DOMAgent.NodeId} parentId
+ * @param {!DOMAgent.NodeId} prevId
+ * @param {!DOMAgent.Node} payload
+ */
+ _childNodeInserted(parentId, prevId, payload) {
+ var parent = this._idToDOMNode[parentId];
+ var prev = this._idToDOMNode[prevId];
+ var node = parent._insertChild(prev, payload);
+ this._idToDOMNode[node.id] = node;
+ this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeInserted, node);
+ this._scheduleMutationEvent(node);
+ }
+
+ /**
+ * @param {!DOMAgent.NodeId} parentId
+ * @param {!DOMAgent.NodeId} nodeId
+ */
+ _childNodeRemoved(parentId, nodeId) {
+ var parent = this._idToDOMNode[parentId];
+ var node = this._idToDOMNode[nodeId];
+ parent._removeChild(node);
+ this._unbind(node);
+ this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeRemoved, {node: node, parent: parent});
+ this._scheduleMutationEvent(node);
+ }
+
+ /**
+ * @param {!DOMAgent.NodeId} hostId
+ * @param {!DOMAgent.Node} root
+ */
+ _shadowRootPushed(hostId, root) {
+ var host = this._idToDOMNode[hostId];
+ if (!host)
+ return;
+ var node = WebInspector.DOMNode.create(this, host.ownerDocument, true, root);
+ node.parentNode = host;
+ this._idToDOMNode[node.id] = node;
+ host._shadowRoots.unshift(node);
+ this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeInserted, node);
+ this._scheduleMutationEvent(node);
+ }
+
+ /**
+ * @param {!DOMAgent.NodeId} hostId
+ * @param {!DOMAgent.NodeId} rootId
+ */
+ _shadowRootPopped(hostId, rootId) {
+ var host = this._idToDOMNode[hostId];
+ if (!host)
+ return;
+ var root = this._idToDOMNode[rootId];
+ if (!root)
+ return;
+ host._removeChild(root);
+ this._unbind(root);
+ this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeRemoved, {node: root, parent: host});
+ this._scheduleMutationEvent(root);
+ }
+
+ /**
+ * @param {!DOMAgent.NodeId} parentId
+ * @param {!DOMAgent.Node} pseudoElement
+ */
+ _pseudoElementAdded(parentId, pseudoElement) {
+ var parent = this._idToDOMNode[parentId];
+ if (!parent)
+ return;
+ var node = WebInspector.DOMNode.create(this, parent.ownerDocument, false, pseudoElement);
+ node.parentNode = parent;
+ this._idToDOMNode[node.id] = node;
+ console.assert(!parent._pseudoElements.get(node.pseudoType()));
+ parent._pseudoElements.set(node.pseudoType(), node);
+ this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeInserted, node);
+ this._scheduleMutationEvent(node);
+ }
+
+ /**
+ * @param {!DOMAgent.NodeId} parentId
+ * @param {!DOMAgent.NodeId} pseudoElementId
+ */
+ _pseudoElementRemoved(parentId, pseudoElementId) {
+ var parent = this._idToDOMNode[parentId];
+ if (!parent)
+ return;
+ var pseudoElement = this._idToDOMNode[pseudoElementId];
+ if (!pseudoElement)
+ return;
+ parent._removeChild(pseudoElement);
+ this._unbind(pseudoElement);
+ this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeRemoved, {node: pseudoElement, parent: parent});
+ this._scheduleMutationEvent(pseudoElement);
+ }
+
+ /**
+ * @param {!DOMAgent.NodeId} insertionPointId
+ * @param {!Array.<!DOMAgent.BackendNode>} distributedNodes
+ */
+ _distributedNodesUpdated(insertionPointId, distributedNodes) {
+ var insertionPoint = this._idToDOMNode[insertionPointId];
+ if (!insertionPoint)
+ return;
+ insertionPoint._setDistributedNodePayloads(distributedNodes);
+ this.dispatchEventToListeners(WebInspector.DOMModel.Events.DistributedNodesChanged, insertionPoint);
+ this._scheduleMutationEvent(insertionPoint);
+ }
+
+ /**
+ * @param {!WebInspector.DOMNode} node
+ */
+ _unbind(node) {
+ delete this._idToDOMNode[node.id];
+ for (var i = 0; node._children && i < node._children.length; ++i)
+ this._unbind(node._children[i]);
+ for (var i = 0; i < node._shadowRoots.length; ++i)
+ this._unbind(node._shadowRoots[i]);
+ var pseudoElements = node.pseudoElements();
+ for (var value of pseudoElements.values())
+ this._unbind(value);
+ if (node._templateContent)
+ this._unbind(node._templateContent);
+ }
+
+ /**
+ * @param {!DOMAgent.BackendNodeId} backendNodeId
+ */
+ _inspectNodeRequested(backendNodeId) {
+ var deferredNode = new WebInspector.DeferredDOMNode(this.target(), backendNodeId);
+ this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeInspected, deferredNode);
+ }
+
+ /**
+ * @param {string} query
+ * @param {boolean} includeUserAgentShadowDOM
+ * @param {function(number)} searchCallback
+ */
+ performSearch(query, includeUserAgentShadowDOM, searchCallback) {
+ WebInspector.DOMModel.cancelSearch();
+
+ /**
+ * @param {?Protocol.Error} error
+ * @param {string} searchId
+ * @param {number} resultsCount
+ * @this {WebInspector.DOMModel}
+ */
+ function callback(error, searchId, resultsCount) {
+ this._searchId = searchId;
+ searchCallback(resultsCount);
+ }
+ this._agent.performSearch(query, includeUserAgentShadowDOM, callback.bind(this));
+ }
+
+ /**
+ * @param {string} query
+ * @param {boolean} includeUserAgentShadowDOM
+ * @return {!Promise.<number>}
+ */
+ performSearchPromise(query, includeUserAgentShadowDOM) {
+ return new Promise(performSearch.bind(this));
+
+ /**
+ * @param {function(number)} resolve
+ * @this {WebInspector.DOMModel}
+ */
+ function performSearch(resolve) {
+ this._agent.performSearch(query, includeUserAgentShadowDOM, callback.bind(this));
+
+ /**
+ * @param {?Protocol.Error} error
+ * @param {string} searchId
+ * @param {number} resultsCount
+ * @this {WebInspector.DOMModel}
+ */
+ function callback(error, searchId, resultsCount) {
+ if (!error)
+ this._searchId = searchId;
+ resolve(error ? 0 : resultsCount);
+ }
+ }
+ }
+
+ /**
+ * @param {number} index
+ * @param {?function(?WebInspector.DOMNode)} callback
+ */
+ searchResult(index, callback) {
+ if (this._searchId)
+ this._agent.getSearchResults(this._searchId, index, index + 1, searchResultsCallback.bind(this));
+ else
+ callback(null);
+
+ /**
+ * @param {?Protocol.Error} error
+ * @param {!Array.<number>} nodeIds
+ * @this {WebInspector.DOMModel}
+ */
+ function searchResultsCallback(error, nodeIds) {
+ if (error) {
+ console.error(error);
+ callback(null);
+ return;
+ }
+ if (nodeIds.length !== 1)
+ return;
+
+ callback(this.nodeForId(nodeIds[0]));
+ }
+ }
- this._agent.requestChildNodes(this.id, depth, mycallback.bind(this));
- },
+ _cancelSearch() {
+ if (this._searchId) {
+ this._agent.discardSearchResults(this._searchId);
+ delete this._searchId;
+ }
+ }
- /**
- * @param {function(?Protocol.Error, string)=} callback
- */
- getOuterHTML: function(callback)
- {
- this._agent.getOuterHTML(this.id, callback);
- },
+ /**
+ * @param {!DOMAgent.NodeId} nodeId
+ * @return {!Promise<!Array<string>>}
+ */
+ classNamesPromise(nodeId) {
+ return new Promise(promiseBody.bind(this));
/**
- * @param {string} html
- * @param {function(?Protocol.Error)=} callback
+ * @param {function(!Array<string>)} fulfill
+ * @this {WebInspector.DOMModel}
*/
- setOuterHTML: function(html, callback)
- {
- this._agent.setOuterHTML(this.id, html, this._domModel._markRevision(this, callback));
- },
+ function promiseBody(fulfill) {
+ this._agent.collectClassNamesFromSubtree(nodeId, classNamesCallback);
- /**
- * @param {function(?Protocol.Error, !DOMAgent.NodeId=)=} callback
- */
- removeNode: function(callback)
- {
- this._agent.removeNode(this.id, this._domModel._markRevision(this, callback));
- },
+ /**
+ * @param {?string} error
+ * @param {?Array<string>} classNames
+ */
+ function classNamesCallback(error, classNames) {
+ if (!error && classNames)
+ fulfill(classNames);
+ else
+ fulfill([]);
+ }
+ }
+ }
+
+ /**
+ * @param {!DOMAgent.NodeId} nodeId
+ * @param {string} selectors
+ * @param {function(?DOMAgent.NodeId)=} callback
+ */
+ querySelector(nodeId, selectors, callback) {
+ this._agent.querySelector(nodeId, selectors, this._wrapClientCallback(callback));
+ }
+
+ /**
+ * @param {!DOMAgent.NodeId} nodeId
+ * @param {string} selectors
+ * @param {function(!Array.<!DOMAgent.NodeId>=)=} callback
+ */
+ querySelectorAll(nodeId, selectors, callback) {
+ this._agent.querySelectorAll(nodeId, selectors, this._wrapClientCallback(callback));
+ }
+
+ /**
+ * @param {!DOMAgent.NodeId=} nodeId
+ * @param {string=} mode
+ * @param {!DOMAgent.BackendNodeId=} backendNodeId
+ * @param {!RuntimeAgent.RemoteObjectId=} objectId
+ */
+ highlightDOMNode(nodeId, mode, backendNodeId, objectId) {
+ this.highlightDOMNodeWithConfig(nodeId, {mode: mode}, backendNodeId, objectId);
+ }
+
+ /**
+ * @param {!DOMAgent.NodeId=} nodeId
+ * @param {!{mode: (string|undefined), showInfo: (boolean|undefined), selectors: (string|undefined)}=} config
+ * @param {!DOMAgent.BackendNodeId=} backendNodeId
+ * @param {!RuntimeAgent.RemoteObjectId=} objectId
+ */
+ highlightDOMNodeWithConfig(nodeId, config, backendNodeId, objectId) {
+ if (WebInspector.DOMModel._highlightDisabled)
+ return;
+ config = config || {mode: 'all', showInfo: undefined, selectors: undefined};
+ if (this._hideDOMNodeHighlightTimeout) {
+ clearTimeout(this._hideDOMNodeHighlightTimeout);
+ delete this._hideDOMNodeHighlightTimeout;
+ }
+ var highlightConfig = this._buildHighlightConfig(config.mode);
+ if (typeof config.showInfo !== 'undefined')
+ highlightConfig.showInfo = config.showInfo;
+ if (typeof config.selectors !== 'undefined')
+ highlightConfig.selectorList = config.selectors;
+ this._highlighter.highlightDOMNode(this.nodeForId(nodeId || 0), highlightConfig, backendNodeId, objectId);
+ }
+
+ /**
+ * @param {!DOMAgent.NodeId} nodeId
+ */
+ highlightDOMNodeForTwoSeconds(nodeId) {
+ this.highlightDOMNode(nodeId);
+ this._hideDOMNodeHighlightTimeout =
+ setTimeout(WebInspector.DOMModel.hideDOMNodeHighlight.bind(WebInspector.DOMModel), 2000);
+ }
+
+ /**
+ * @param {!PageAgent.FrameId} frameId
+ */
+ highlightFrame(frameId) {
+ if (WebInspector.DOMModel._highlightDisabled)
+ return;
+ this._highlighter.highlightFrame(frameId);
+ }
+
+ /**
+ * @param {!DOMAgent.InspectMode} mode
+ * @param {function(?Protocol.Error)=} callback
+ */
+ setInspectMode(mode, callback) {
+ /**
+ * @this {WebInspector.DOMModel}
+ */
+ function onDocumentAvailable() {
+ this._inspectModeEnabled = mode !== DOMAgent.InspectMode.None;
+ this.dispatchEventToListeners(WebInspector.DOMModel.Events.InspectModeWillBeToggled, this._inspectModeEnabled);
+ this._highlighter.setInspectMode(mode, this._buildHighlightConfig(), callback);
+ }
+ this.requestDocument(onDocumentAvailable.bind(this));
+ }
+
+ /**
+ * @return {boolean}
+ */
+ inspectModeEnabled() {
+ return this._inspectModeEnabled;
+ }
+
+ /**
+ * @param {string=} mode
+ * @return {!DOMAgent.HighlightConfig}
+ */
+ _buildHighlightConfig(mode) {
+ mode = mode || 'all';
+ var showRulers = WebInspector.moduleSetting('showMetricsRulers').get();
+ var highlightConfig = {showInfo: mode === 'all', showRulers: showRulers, showExtensionLines: showRulers};
+ if (mode === 'all' || mode === 'content')
+ highlightConfig.contentColor = WebInspector.Color.PageHighlight.Content.toProtocolRGBA();
+
+ if (mode === 'all' || mode === 'padding')
+ highlightConfig.paddingColor = WebInspector.Color.PageHighlight.Padding.toProtocolRGBA();
+
+ if (mode === 'all' || mode === 'border')
+ highlightConfig.borderColor = WebInspector.Color.PageHighlight.Border.toProtocolRGBA();
+
+ if (mode === 'all' || mode === 'margin')
+ highlightConfig.marginColor = WebInspector.Color.PageHighlight.Margin.toProtocolRGBA();
+
+ if (mode === 'all') {
+ highlightConfig.eventTargetColor = WebInspector.Color.PageHighlight.EventTarget.toProtocolRGBA();
+ highlightConfig.shapeColor = WebInspector.Color.PageHighlight.Shape.toProtocolRGBA();
+ highlightConfig.shapeMarginColor = WebInspector.Color.PageHighlight.ShapeMargin.toProtocolRGBA();
+ highlightConfig.displayAsMaterial = Runtime.experiments.isEnabled('inspectTooltip');
+ }
+ return highlightConfig;
+ }
+
+ /**
+ * @param {!WebInspector.DOMNode} node
+ * @param {function(?Protocol.Error, ...)=} callback
+ * @return {function(...)}
+ * @template T
+ */
+ _markRevision(node, callback) {
+ /**
+ * @param {?Protocol.Error} error
+ * @this {WebInspector.DOMModel}
+ */
+ function wrapperFunction(error) {
+ if (!error)
+ this.markUndoableState();
+
+ if (callback)
+ callback.apply(this, arguments);
+ }
+ return wrapperFunction.bind(this);
+ }
- /**
- * @param {function(?string)=} callback
- */
- copyNode: function(callback)
- {
- function copy(error, text)
- {
- if (!error)
- InspectorFrontendHost.copyText(text);
- if (callback)
- callback(error ? null : text);
- }
- this._agent.getOuterHTML(this.id, copy);
- },
+ markUndoableState() {
+ this._agent.markUndoableState();
+ }
+ /**
+ * @param {function(?Protocol.Error)=} callback
+ */
+ undo(callback) {
/**
- * @return {string}
+ * @param {?Protocol.Error} error
+ * @this {WebInspector.DOMModel}
*/
- path: function()
- {
- /**
- * @param {?WebInspector.DOMNode} node
- */
- function canPush(node)
- {
- return node && ("index" in node || (node.isShadowRoot() && node.parentNode)) && node._nodeName.length;
- }
+ function mycallback(error) {
+ this.dispatchEventToListeners(WebInspector.DOMModel.Events.UndoRedoCompleted);
+ callback(error);
+ }
- var path = [];
- var node = this;
- while (canPush(node)) {
- var index = typeof node.index === "number" ? node.index : (node.shadowRootType() === WebInspector.DOMNode.ShadowRootTypes.UserAgent ? "u" : "a");
- path.push([index, node._nodeName]);
- node = node.parentNode;
- }
- path.reverse();
- return path.join(",");
- },
+ this.dispatchEventToListeners(WebInspector.DOMModel.Events.UndoRedoRequested);
+ this._agent.undo(callback);
+ }
+ /**
+ * @param {function(?Protocol.Error)=} callback
+ */
+ redo(callback) {
/**
- * @param {!WebInspector.DOMNode} node
- * @return {boolean}
+ * @param {?Protocol.Error} error
+ * @this {WebInspector.DOMModel}
*/
- isAncestor: function(node)
- {
- if (!node)
- return false;
-
- var currentNode = node.parentNode;
- while (currentNode) {
- if (this === currentNode)
- return true;
- currentNode = currentNode.parentNode;
- }
- return false;
- },
+ function mycallback(error) {
+ this.dispatchEventToListeners(WebInspector.DOMModel.Events.UndoRedoCompleted);
+ callback(error);
+ }
- /**
- * @param {!WebInspector.DOMNode} descendant
- * @return {boolean}
- */
- isDescendant: function(descendant)
- {
- return descendant !== null && descendant.isAncestor(this);
- },
+ this.dispatchEventToListeners(WebInspector.DOMModel.Events.UndoRedoRequested);
+ this._agent.redo(callback);
+ }
+
+ /**
+ * @param {?WebInspector.DOMNodeHighlighter} highlighter
+ */
+ setHighlighter(highlighter) {
+ this._highlighter = highlighter || this._defaultHighlighter;
+ }
+
+ /**
+ * @param {number} x
+ * @param {number} y
+ * @param {function(?WebInspector.DOMNode)} callback
+ */
+ nodeForLocation(x, y, callback) {
+ this._agent.getNodeForLocation(x, y, mycallback.bind(this));
+
+ /**
+ * @param {?Protocol.Error} error
+ * @param {number} nodeId
+ * @this {WebInspector.DOMModel}
+ */
+ function mycallback(error, nodeId) {
+ if (error) {
+ callback(null);
+ return;
+ }
+ callback(this.nodeForId(nodeId));
+ }
+ }
+
+ /**
+ * @param {!WebInspector.RemoteObject} object
+ * @param {function(?WebInspector.DOMNode)} callback
+ */
+ pushObjectAsNodeToFrontend(object, callback) {
+ if (object.isNode())
+ this.pushNodeToFrontend(object.objectId, callback);
+ else
+ callback(null);
+ }
+
+ /**
+ * @override
+ * @return {!Promise}
+ */
+ suspendModel() {
+ return new Promise(promiseBody.bind(this));
+
+ /**
+ * @param {function()} fulfill
+ * @this {WebInspector.DOMModel}
+ */
+ function promiseBody(fulfill) {
+ this._agent.disable(callback.bind(this));
+
+ /**
+ * @this {WebInspector.DOMModel}
+ */
+ function callback() {
+ this._setDocument(null);
+ fulfill();
+ }
+ }
+ }
- /**
- * @return {?PageAgent.FrameId}
- */
- frameId: function()
- {
- var node = this.parentNode || this;
- while (!node._frameOwnerFrameId && node.parentNode)
- node = node.parentNode;
- return node._frameOwnerFrameId;
- },
+ /**
+ * @override
+ * @return {!Promise}
+ */
+ resumeModel() {
+ return new Promise(promiseBody.bind(this));
/**
- * @param {!Array.<string>} attrs
- * @return {boolean}
+ * @param {function()} fulfill
+ * @this {WebInspector.DOMModel}
*/
- _setAttributesPayload: function(attrs)
- {
- var attributesChanged = !this._attributes || attrs.length !== this._attributes.length * 2;
- var oldAttributesMap = this._attributesMap || {};
-
- this._attributes = [];
- this._attributesMap = {};
+ function promiseBody(fulfill) {
+ this._agent.enable(fulfill);
+ }
+ }
+
+ /**
+ * @param {!DOMAgent.NodeId} nodeId
+ */
+ nodeHighlightRequested(nodeId) {
+ var node = this.nodeForId(nodeId);
+ if (!node)
+ return;
+
+ this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeHighlightedInOverlay, node);
+ }
+};
- for (var i = 0; i < attrs.length; i += 2) {
- var name = attrs[i];
- var value = attrs[i + 1];
- this._addAttribute(name, value);
+/** @enum {symbol} */
+WebInspector.DOMModel.Events = {
+ AttrModified: Symbol('AttrModified'),
+ AttrRemoved: Symbol('AttrRemoved'),
+ CharacterDataModified: Symbol('CharacterDataModified'),
+ DOMMutated: Symbol('DOMMutated'),
+ NodeInserted: Symbol('NodeInserted'),
+ NodeInspected: Symbol('NodeInspected'),
+ NodeHighlightedInOverlay: Symbol('NodeHighlightedInOverlay'),
+ NodeRemoved: Symbol('NodeRemoved'),
+ DocumentUpdated: Symbol('DocumentUpdated'),
+ ChildNodeCountUpdated: Symbol('ChildNodeCountUpdated'),
+ UndoRedoRequested: Symbol('UndoRedoRequested'),
+ UndoRedoCompleted: Symbol('UndoRedoCompleted'),
+ DistributedNodesChanged: Symbol('DistributedNodesChanged'),
+ ModelSuspended: Symbol('ModelSuspended'),
+ InspectModeWillBeToggled: Symbol('InspectModeWillBeToggled'),
+ MarkersChanged: Symbol('MarkersChanged')
+};
- if (attributesChanged)
- continue;
- if (!oldAttributesMap[name] || oldAttributesMap[name].value !== value)
- attributesChanged = true;
- }
- return attributesChanged;
- },
+/**
+ * @implements {DOMAgent.Dispatcher}
+ * @unrestricted
+ */
+WebInspector.DOMDispatcher = class {
+ /**
+ * @param {!WebInspector.DOMModel} domModel
+ */
+ constructor(domModel) {
+ this._domModel = domModel;
+ }
+
+ /**
+ * @override
+ */
+ documentUpdated() {
+ this._domModel._documentUpdated();
+ }
+
+ /**
+ * @override
+ * @param {!DOMAgent.NodeId} nodeId
+ */
+ inspectNodeRequested(nodeId) {
+ this._domModel._inspectNodeRequested(nodeId);
+ }
+
+ /**
+ * @override
+ * @param {!DOMAgent.NodeId} nodeId
+ * @param {string} name
+ * @param {string} value
+ */
+ attributeModified(nodeId, name, value) {
+ this._domModel._attributeModified(nodeId, name, value);
+ }
+
+ /**
+ * @override
+ * @param {!DOMAgent.NodeId} nodeId
+ * @param {string} name
+ */
+ attributeRemoved(nodeId, name) {
+ this._domModel._attributeRemoved(nodeId, name);
+ }
+
+ /**
+ * @override
+ * @param {!Array.<!DOMAgent.NodeId>} nodeIds
+ */
+ inlineStyleInvalidated(nodeIds) {
+ this._domModel._inlineStyleInvalidated(nodeIds);
+ }
+
+ /**
+ * @override
+ * @param {!DOMAgent.NodeId} nodeId
+ * @param {string} characterData
+ */
+ characterDataModified(nodeId, characterData) {
+ this._domModel._characterDataModified(nodeId, characterData);
+ }
+
+ /**
+ * @override
+ * @param {!DOMAgent.NodeId} parentId
+ * @param {!Array.<!DOMAgent.Node>} payloads
+ */
+ setChildNodes(parentId, payloads) {
+ this._domModel._setChildNodes(parentId, payloads);
+ }
+
+ /**
+ * @override
+ * @param {!DOMAgent.NodeId} nodeId
+ * @param {number} childNodeCount
+ */
+ childNodeCountUpdated(nodeId, childNodeCount) {
+ this._domModel._childNodeCountUpdated(nodeId, childNodeCount);
+ }
+
+ /**
+ * @override
+ * @param {!DOMAgent.NodeId} parentNodeId
+ * @param {!DOMAgent.NodeId} previousNodeId
+ * @param {!DOMAgent.Node} payload
+ */
+ childNodeInserted(parentNodeId, previousNodeId, payload) {
+ this._domModel._childNodeInserted(parentNodeId, previousNodeId, payload);
+ }
+
+ /**
+ * @override
+ * @param {!DOMAgent.NodeId} parentNodeId
+ * @param {!DOMAgent.NodeId} nodeId
+ */
+ childNodeRemoved(parentNodeId, nodeId) {
+ this._domModel._childNodeRemoved(parentNodeId, nodeId);
+ }
+
+ /**
+ * @override
+ * @param {!DOMAgent.NodeId} hostId
+ * @param {!DOMAgent.Node} root
+ */
+ shadowRootPushed(hostId, root) {
+ this._domModel._shadowRootPushed(hostId, root);
+ }
+
+ /**
+ * @override
+ * @param {!DOMAgent.NodeId} hostId
+ * @param {!DOMAgent.NodeId} rootId
+ */
+ shadowRootPopped(hostId, rootId) {
+ this._domModel._shadowRootPopped(hostId, rootId);
+ }
+
+ /**
+ * @override
+ * @param {!DOMAgent.NodeId} parentId
+ * @param {!DOMAgent.Node} pseudoElement
+ */
+ pseudoElementAdded(parentId, pseudoElement) {
+ this._domModel._pseudoElementAdded(parentId, pseudoElement);
+ }
+
+ /**
+ * @override
+ * @param {!DOMAgent.NodeId} parentId
+ * @param {!DOMAgent.NodeId} pseudoElementId
+ */
+ pseudoElementRemoved(parentId, pseudoElementId) {
+ this._domModel._pseudoElementRemoved(parentId, pseudoElementId);
+ }
+
+ /**
+ * @override
+ * @param {!DOMAgent.NodeId} insertionPointId
+ * @param {!Array.<!DOMAgent.BackendNode>} distributedNodes
+ */
+ distributedNodesUpdated(insertionPointId, distributedNodes) {
+ this._domModel._distributedNodesUpdated(insertionPointId, distributedNodes);
+ }
+
+ /**
+ * @override
+ * @param {!DOMAgent.NodeId} nodeId
+ */
+ nodeHighlightRequested(nodeId) {
+ this._domModel.nodeHighlightRequested(nodeId);
+ }
+};
- /**
- * @param {!WebInspector.DOMNode} prev
- * @param {!DOMAgent.Node} payload
- * @return {!WebInspector.DOMNode}
- */
- _insertChild: function(prev, payload)
- {
- var node = WebInspector.DOMNode.create(this._domModel, this.ownerDocument, this._isInShadowTree, payload);
- this._children.splice(this._children.indexOf(prev) + 1, 0, node);
- this._renumber();
- return node;
- },
+/**
+ * @interface
+ */
+WebInspector.DOMNodeHighlighter = function() {};
- /**
- * @param {!WebInspector.DOMNode} node
- */
- _removeChild: function(node)
- {
- if (node.pseudoType()) {
- this._pseudoElements.delete(node.pseudoType());
- } else {
- var shadowRootIndex = this._shadowRoots.indexOf(node);
- if (shadowRootIndex !== -1) {
- this._shadowRoots.splice(shadowRootIndex, 1);
- } else {
- console.assert(this._children.indexOf(node) !== -1);
- this._children.splice(this._children.indexOf(node), 1);
- }
- }
- node.parentNode = null;
- this._subtreeMarkerCount -= node._subtreeMarkerCount;
- if (node._subtreeMarkerCount)
- this._domModel.dispatchEventToListeners(WebInspector.DOMModel.Events.MarkersChanged, this);
- this._renumber();
- },
+WebInspector.DOMNodeHighlighter.prototype = {
+ /**
+ * @param {?WebInspector.DOMNode} node
+ * @param {!DOMAgent.HighlightConfig} config
+ * @param {!DOMAgent.BackendNodeId=} backendNodeId
+ * @param {!RuntimeAgent.RemoteObjectId=} objectId
+ */
+ highlightDOMNode: function(node, config, backendNodeId, objectId) {},
+
+ /**
+ * @param {!DOMAgent.InspectMode} mode
+ * @param {!DOMAgent.HighlightConfig} config
+ * @param {function(?Protocol.Error)=} callback
+ */
+ setInspectMode: function(mode, config, callback) {},
+
+ /**
+ * @param {!PageAgent.FrameId} frameId
+ */
+ highlightFrame: function(frameId) {}
+};
- /**
- * @param {!Array.<!DOMAgent.Node>} payloads
- */
- _setChildrenPayload: function(payloads)
- {
- // We set children in the constructor.
- if (this._contentDocument)
- return;
-
- this._children = [];
- for (var i = 0; i < payloads.length; ++i) {
- var payload = payloads[i];
- var node = WebInspector.DOMNode.create(this._domModel, this.ownerDocument, this._isInShadowTree, payload);
- this._children.push(node);
- }
- this._renumber();
- },
+/**
+ * @implements {WebInspector.DOMNodeHighlighter}
+ * @unrestricted
+ */
+WebInspector.DefaultDOMNodeHighlighter = class {
+ /**
+ * @param {!Protocol.DOMAgent} agent
+ */
+ constructor(agent) {
+ this._agent = agent;
+ }
+
+ /**
+ * @override
+ * @param {?WebInspector.DOMNode} node
+ * @param {!DOMAgent.HighlightConfig} config
+ * @param {!DOMAgent.BackendNodeId=} backendNodeId
+ * @param {!RuntimeAgent.RemoteObjectId=} objectId
+ */
+ highlightDOMNode(node, config, backendNodeId, objectId) {
+ if (objectId || node || backendNodeId)
+ this._agent.highlightNode(config, (objectId || backendNodeId) ? undefined : node.id, backendNodeId, objectId);
+ else
+ this._agent.hideHighlight();
+ }
+
+ /**
+ * @override
+ * @param {!DOMAgent.InspectMode} mode
+ * @param {!DOMAgent.HighlightConfig} config
+ * @param {function(?Protocol.Error)=} callback
+ */
+ setInspectMode(mode, config, callback) {
+ this._agent.setInspectMode(mode, config, callback);
+ }
+
+ /**
+ * @override
+ * @param {!PageAgent.FrameId} frameId
+ */
+ highlightFrame(frameId) {
+ this._agent.highlightFrame(
+ frameId, WebInspector.Color.PageHighlight.Content.toProtocolRGBA(),
+ WebInspector.Color.PageHighlight.ContentOutline.toProtocolRGBA());
+ }
+};
- /**
- * @param {!Array.<!DOMAgent.Node>|undefined} payloads
- */
- _setPseudoElements: function(payloads)
- {
- this._pseudoElements = new Map();
- if (!payloads)
- return;
-
- for (var i = 0; i < payloads.length; ++i) {
- var node = WebInspector.DOMNode.create(this._domModel, this.ownerDocument, this._isInShadowTree, payloads[i]);
- node.parentNode = this;
- this._pseudoElements.set(node.pseudoType(), node);
- }
- },
- /**
- * @param {!Array.<!DOMAgent.BackendNode>} payloads
- */
- _setDistributedNodePayloads: function(payloads)
- {
- this._distributedNodes = [];
- for (var payload of payloads)
- this._distributedNodes.push(new WebInspector.DOMNodeShortcut(this._domModel.target(), payload.backendNodeId, payload.nodeType, payload.nodeName));
- },
-
- _renumber: function()
- {
- this._childNodeCount = this._children.length;
- if (this._childNodeCount === 0) {
- this.firstChild = null;
- this.lastChild = null;
- return;
- }
- this.firstChild = this._children[0];
- this.lastChild = this._children[this._childNodeCount - 1];
- for (var i = 0; i < this._childNodeCount; ++i) {
- var child = this._children[i];
- child.index = i;
- child.nextSibling = i + 1 < this._childNodeCount ? this._children[i + 1] : null;
- child.previousSibling = i - 1 >= 0 ? this._children[i - 1] : null;
- child.parentNode = this;
- }
- },
-
- /**
- * @param {string} name
- * @param {string} value
- */
- _addAttribute: function(name, value)
- {
- var attr = {
- name: name,
- value: value,
- _node: this
- };
- this._attributesMap[name] = attr;
- this._attributes.push(attr);
- },
-
- /**
- * @param {string} name
- * @param {string} value
- */
- _setAttribute: function(name, value)
- {
- var attr = this._attributesMap[name];
- if (attr)
- attr.value = value;
- else
- this._addAttribute(name, value);
- },
-
- /**
- * @param {string} name
- */
- _removeAttribute: function(name)
- {
- var attr = this._attributesMap[name];
- if (attr) {
- this._attributes.remove(attr);
- delete this._attributesMap[name];
- }
- },
-
- /**
- * @param {!WebInspector.DOMNode} targetNode
- * @param {?WebInspector.DOMNode} anchorNode
- * @param {function(?Protocol.Error, !DOMAgent.NodeId=)=} callback
- */
- copyTo: function(targetNode, anchorNode, callback)
- {
- this._agent.copyTo(this.id, targetNode.id, anchorNode ? anchorNode.id : undefined, this._domModel._markRevision(this, callback));
- },
-
- /**
- * @param {!WebInspector.DOMNode} targetNode
- * @param {?WebInspector.DOMNode} anchorNode
- * @param {function(?Protocol.Error, !DOMAgent.NodeId=)=} callback
- */
- moveTo: function(targetNode, anchorNode, callback)
- {
- this._agent.moveTo(this.id, targetNode.id, anchorNode ? anchorNode.id : undefined, this._domModel._markRevision(this, callback));
- },
-
- /**
- * @return {boolean}
- */
- isXMLNode: function()
- {
- return !!this._xmlVersion;
- },
-
- /**
- * @param {string} name
- * @param {?*} value
- */
- setMarker: function(name, value)
- {
- if (value === null) {
- if (!this._markers.has(name))
- return;
-
- this._markers.delete(name);
- for (var node = this; node; node = node.parentNode)
- --node._subtreeMarkerCount;
- for (var node = this; node; node = node.parentNode)
- this._domModel.dispatchEventToListeners(WebInspector.DOMModel.Events.MarkersChanged, node);
- return;
- }
-
- if (this.parentNode && !this._markers.has(name)) {
- for (var node = this; node; node = node.parentNode)
- ++node._subtreeMarkerCount;
- }
- this._markers.set(name, value);
- for (var node = this; node; node = node.parentNode)
- this._domModel.dispatchEventToListeners(WebInspector.DOMModel.Events.MarkersChanged, node);
- },
-
- /**
- * @param {string} name
- * @return {?T}
- * @template T
- */
- marker: function(name)
- {
- return this._markers.get(name) || null;
- },
-
- /**
- * @param {function(!WebInspector.DOMNode, string)} visitor
- */
- traverseMarkers: function(visitor)
- {
- /**
- * @param {!WebInspector.DOMNode} node
- */
- function traverse(node)
- {
- if (!node._subtreeMarkerCount)
- return;
- for (var marker of node._markers.keys())
- visitor(node, marker);
- if (!node._children)
- return;
- for (var child of node._children)
- traverse(child);
- }
- traverse(this);
- },
-
- /**
- * @param {string} url
- * @return {?string}
- */
- resolveURL: function(url)
- {
- if (!url)
- return url;
- for (var frameOwnerCandidate = this; frameOwnerCandidate; frameOwnerCandidate = frameOwnerCandidate.parentNode) {
- if (frameOwnerCandidate.baseURL)
- return WebInspector.ParsedURL.completeURL(frameOwnerCandidate.baseURL, url);
- }
- return null;
- },
-
- /**
- * @param {string=} mode
- * @param {!RuntimeAgent.RemoteObjectId=} objectId
- */
- highlight: function(mode, objectId)
- {
- this._domModel.highlightDOMNode(this.id, mode, undefined, objectId);
- },
-
- highlightForTwoSeconds: function()
- {
- this._domModel.highlightDOMNodeForTwoSeconds(this.id);
- },
-
- /**
- * @param {string=} objectGroup
- * @param {function(?WebInspector.RemoteObject)=} callback
- */
- resolveToObject: function(objectGroup, callback)
- {
- this._agent.resolveNode(this.id, objectGroup, mycallback.bind(this));
-
- /**
- * @param {?Protocol.Error} error
- * @param {!RuntimeAgent.RemoteObject} object
- * @this {WebInspector.DOMNode}
- */
- function mycallback(error, object)
- {
- if (!callback)
- return;
-
- if (error || !object)
- callback(null);
- else
- callback(this.target().runtimeModel.createRemoteObject(object));
- }
- },
-
- /**
- * @param {string=} objectGroup
- * @return {!Promise<!WebInspector.RemoteObject>}
- */
- resolveToObjectPromise: function(objectGroup)
- {
- return new Promise(resolveToObject.bind(this));
- /**
- * @param {function(?)} fulfill
- * @param {function(*)} reject
- * @this {WebInspector.DOMNode}
- */
- function resolveToObject(fulfill, reject)
- {
- this.resolveToObject(objectGroup, mycallback);
- function mycallback(object)
- {
- if (object)
- fulfill(object);
- else
- reject(null);
- }
- }
- },
-
- /**
- * @param {function(?DOMAgent.BoxModel)} callback
- */
- boxModel: function(callback)
- {
- this._agent.getBoxModel(this.id, this._domModel._wrapClientCallback(callback));
- },
-
- setAsInspectedNode: function()
- {
- var node = this;
- while (true) {
- var ancestor = node.ancestorUserAgentShadowRoot();
- if (!ancestor)
- break;
- ancestor = node.ancestorShadowHost();
- if (!ancestor)
- break;
- // User agent shadow root, keep climbing up.
- node = ancestor;
- }
- this._agent.setInspectedNode(node.id);
- },
-
- /**
- * @return {?WebInspector.DOMNode}
- */
- enclosingElementOrSelf: function()
- {
- var node = this;
- if (node && node.nodeType() === Node.TEXT_NODE && node.parentNode)
- node = node.parentNode;
-
- if (node && node.nodeType() !== Node.ELEMENT_NODE)
- node = null;
- return node;
- },
-
- __proto__: WebInspector.SDKObject.prototype
-};
-
-/**
- * @param {!WebInspector.Target} target
- * @param {number} backendNodeId
- * @constructor
- */
-WebInspector.DeferredDOMNode = function(target, backendNodeId)
-{
- this._domModel = WebInspector.DOMModel.fromTarget(target);
- this._backendNodeId = backendNodeId;
-};
-
-WebInspector.DeferredDOMNode.prototype = {
- /**
- * @param {function(?WebInspector.DOMNode)} callback
- */
- resolve: function(callback)
- {
- if (!this._domModel) {
- callback(null);
- return;
- }
-
- this._domModel.pushNodesByBackendIdsToFrontend(new Set([this._backendNodeId]), onGotNode.bind(this));
-
- /**
- * @param {?Map<number, ?WebInspector.DOMNode>} nodeIds
- * @this {WebInspector.DeferredDOMNode}
- */
- function onGotNode(nodeIds)
- {
- callback(nodeIds && (nodeIds.get(this._backendNodeId) || null));
- }
- },
-
- /**
- * @return {!Promise.<!WebInspector.DOMNode>}
- */
- resolvePromise: function()
- {
- /**
- * @param {function(?)} fulfill
- * @param {function(*)} reject
- * @this {WebInspector.DeferredDOMNode}
- */
- function resolveNode(fulfill, reject)
- {
- /**
- * @param {?WebInspector.DOMNode} node
- */
- function mycallback(node)
- {
- fulfill(node);
- }
- this.resolve(mycallback);
- }
- return new Promise(resolveNode.bind(this));
- },
-
- /**
- * @return {number}
- */
- backendNodeId: function()
- {
- return this._backendNodeId;
- },
-
- highlight: function()
- {
- if (this._domModel)
- this._domModel.highlightDOMNode(undefined, undefined, this._backendNodeId);
- }
-};
-
-/**
- * @constructor
- * @param {!WebInspector.Target} target
- * @param {number} backendNodeId
- * @param {number} nodeType
- * @param {string} nodeName
- */
-WebInspector.DOMNodeShortcut = function(target, backendNodeId, nodeType, nodeName)
-{
- this.nodeType = nodeType;
- this.nodeName = nodeName;
- this.deferredNode = new WebInspector.DeferredDOMNode(target, backendNodeId);
-};
-
-/**
- * @extends {WebInspector.DOMNode}
- * @constructor
- * @param {!WebInspector.DOMModel} domModel
- * @param {!DOMAgent.Node} payload
- */
-WebInspector.DOMDocument = function(domModel, payload)
-{
- WebInspector.DOMNode.call(this, domModel);
- this._init(this, false, payload);
- this.documentURL = payload.documentURL || "";
- this.baseURL = payload.baseURL || "";
- this._listeners = {};
-};
-
-WebInspector.DOMDocument.prototype = {
- __proto__: WebInspector.DOMNode.prototype
-};
-
-/**
- * @constructor
- * @extends {WebInspector.SDKModel}
- * @param {!WebInspector.Target} target
- */
-WebInspector.DOMModel = function(target) {
- WebInspector.SDKModel.call(this, WebInspector.DOMModel, target);
-
- this._agent = target.domAgent();
-
- /** @type {!Object.<number, !WebInspector.DOMNode>} */
- this._idToDOMNode = {};
- /** @type {?WebInspector.DOMDocument} */
- this._document = null;
- /** @type {!Object.<number, boolean>} */
- this._attributeLoadNodeIds = {};
- target.registerDOMDispatcher(new WebInspector.DOMDispatcher(this));
-
- this._inspectModeEnabled = false;
-
- this._defaultHighlighter = new WebInspector.DefaultDOMNodeHighlighter(this._agent);
- this._highlighter = this._defaultHighlighter;
-
- this._agent.enable();
-};
-
-/** @enum {symbol} */
-WebInspector.DOMModel.Events = {
- AttrModified: Symbol("AttrModified"),
- AttrRemoved: Symbol("AttrRemoved"),
- CharacterDataModified: Symbol("CharacterDataModified"),
- DOMMutated: Symbol("DOMMutated"),
- NodeInserted: Symbol("NodeInserted"),
- NodeInspected: Symbol("NodeInspected"),
- NodeHighlightedInOverlay: Symbol("NodeHighlightedInOverlay"),
- NodeRemoved: Symbol("NodeRemoved"),
- DocumentUpdated: Symbol("DocumentUpdated"),
- ChildNodeCountUpdated: Symbol("ChildNodeCountUpdated"),
- UndoRedoRequested: Symbol("UndoRedoRequested"),
- UndoRedoCompleted: Symbol("UndoRedoCompleted"),
- DistributedNodesChanged: Symbol("DistributedNodesChanged"),
- ModelSuspended: Symbol("ModelSuspended"),
- InspectModeWillBeToggled: Symbol("InspectModeWillBeToggled"),
- MarkersChanged: Symbol("MarkersChanged")
-};
-
-/**
- * @param {!WebInspector.RemoteObject} object
- */
-WebInspector.DOMModel.highlightObjectAsDOMNode = function(object)
-{
- var domModel = WebInspector.DOMModel.fromTarget(object.target());
- if (domModel)
- domModel.highlightDOMNode(undefined, undefined, undefined, object.objectId);
-};
-
-/**
- * @return {!Array<!WebInspector.DOMModel>}
- */
-WebInspector.DOMModel.instances = function()
-{
- var result = [];
- for (var target of WebInspector.targetManager.targets()) {
- var domModel = WebInspector.DOMModel.fromTarget(target);
- if (domModel)
- result.push(domModel);
- }
- return result;
-};
-
-WebInspector.DOMModel.hideDOMNodeHighlight = function()
-{
- for (var domModel of WebInspector.DOMModel.instances())
- domModel.highlightDOMNode(0);
-};
-
-WebInspector.DOMModel.muteHighlight = function()
-{
- WebInspector.DOMModel.hideDOMNodeHighlight();
- WebInspector.DOMModel._highlightDisabled = true;
-};
-
-WebInspector.DOMModel.unmuteHighlight = function()
-{
- WebInspector.DOMModel._highlightDisabled = false;
-};
-
-WebInspector.DOMModel.cancelSearch = function()
-{
- for (var domModel of WebInspector.DOMModel.instances())
- domModel._cancelSearch();
-};
-
-WebInspector.DOMModel.prototype = {
- /**
- * @param {!WebInspector.DOMNode} node
- */
- _scheduleMutationEvent: function(node)
- {
- if (!this.hasEventListeners(WebInspector.DOMModel.Events.DOMMutated))
- return;
-
- this._lastMutationId = (this._lastMutationId || 0) + 1;
- Promise.resolve().then(callObserve.bind(this, node, this._lastMutationId));
-
- /**
- * @this {WebInspector.DOMModel}
- * @param {!WebInspector.DOMNode} node
- * @param {number} mutationId
- */
- function callObserve(node, mutationId)
- {
- if (!this.hasEventListeners(WebInspector.DOMModel.Events.DOMMutated) || this._lastMutationId !== mutationId)
- return;
-
- this.dispatchEventToListeners(WebInspector.DOMModel.Events.DOMMutated, node);
- }
- },
-
- /**
- * @param {function(!WebInspector.DOMDocument)=} callback
- */
- requestDocument: function(callback)
- {
- if (this._document) {
- if (callback)
- callback(this._document);
- return;
- }
-
- if (this._pendingDocumentRequestCallbacks) {
- this._pendingDocumentRequestCallbacks.push(callback);
- return;
- }
-
- this._pendingDocumentRequestCallbacks = [callback];
-
- /**
- * @this {WebInspector.DOMModel}
- * @param {?Protocol.Error} error
- * @param {!DOMAgent.Node} root
- */
- function onDocumentAvailable(error, root)
- {
- if (!error)
- this._setDocument(root);
-
- for (var i = 0; i < this._pendingDocumentRequestCallbacks.length; ++i) {
- var callback = this._pendingDocumentRequestCallbacks[i];
- if (callback)
- callback(this._document);
- }
- delete this._pendingDocumentRequestCallbacks;
- }
-
- this._agent.getDocument(undefined, undefined, onDocumentAvailable.bind(this));
- },
-
- /**
- * @return {?WebInspector.DOMDocument}
- */
- existingDocument: function()
- {
- return this._document;
- },
-
- /**
- * @param {!RuntimeAgent.RemoteObjectId} objectId
- * @param {function(?WebInspector.DOMNode)=} callback
- */
- pushNodeToFrontend: function(objectId, callback)
- {
- /**
- * @param {?DOMAgent.NodeId} nodeId
- * @this {!WebInspector.DOMModel}
- */
- function mycallback(nodeId)
- {
- callback(nodeId ? this.nodeForId(nodeId) : null);
- }
- this._dispatchWhenDocumentAvailable(this._agent.requestNode.bind(this._agent, objectId), mycallback.bind(this));
- },
-
- /**
- * @param {string} path
- * @param {function(?number)=} callback
- */
- pushNodeByPathToFrontend: function(path, callback)
- {
- this._dispatchWhenDocumentAvailable(this._agent.pushNodeByPathToFrontend.bind(this._agent, path), callback);
- },
-
- /**
- * @param {!Set<number>} backendNodeIds
- * @param {function(?Map<number, ?WebInspector.DOMNode>)} callback
- */
- pushNodesByBackendIdsToFrontend: function(backendNodeIds, callback)
- {
- var backendNodeIdsArray = backendNodeIds.valuesArray();
- /**
- * @param {?Array<!DOMAgent.NodeId>} nodeIds
- * @this {!WebInspector.DOMModel}
- */
- function mycallback(nodeIds)
- {
- if (!nodeIds) {
- callback(null);
- return;
- }
- /** @type {!Map<number, ?WebInspector.DOMNode>} */
- var map = new Map();
- for (var i = 0; i < nodeIds.length; ++i) {
- if (nodeIds[i])
- map.set(backendNodeIdsArray[i], this.nodeForId(nodeIds[i]));
- }
- callback(map);
- }
- this._dispatchWhenDocumentAvailable(this._agent.pushNodesByBackendIdsToFrontend.bind(this._agent, backendNodeIdsArray), mycallback.bind(this));
- },
-
- /**
- * @param {function(!T)=} callback
- * @return {function(?Protocol.Error, !T=)|undefined}
- * @template T
- */
- _wrapClientCallback: function(callback)
- {
- if (!callback)
- return;
- /**
- * @param {?Protocol.Error} error
- * @param {!T=} result
- * @template T
- */
- var wrapper = function(error, result)
- {
- // Caller is responsible for handling the actual error.
- callback(error ? null : result);
- };
- return wrapper;
- },
-
- /**
- * @param {function(function(?Protocol.Error, !T=)=)} func
- * @param {function(!T)=} callback
- * @template T
- */
- _dispatchWhenDocumentAvailable: function(func, callback)
- {
- var callbackWrapper = this._wrapClientCallback(callback);
-
- /**
- * @this {WebInspector.DOMModel}
- */
- function onDocumentAvailable()
- {
- if (this._document)
- func(callbackWrapper);
- else {
- if (callbackWrapper)
- callbackWrapper("No document");
- }
- }
- this.requestDocument(onDocumentAvailable.bind(this));
- },
-
- /**
- * @param {!DOMAgent.NodeId} nodeId
- * @param {string} name
- * @param {string} value
- */
- _attributeModified: function(nodeId, name, value)
- {
- var node = this._idToDOMNode[nodeId];
- if (!node)
- return;
-
- node._setAttribute(name, value);
- this.dispatchEventToListeners(WebInspector.DOMModel.Events.AttrModified, { node: node, name: name });
- this._scheduleMutationEvent(node);
- },
-
- /**
- * @param {!DOMAgent.NodeId} nodeId
- * @param {string} name
- */
- _attributeRemoved: function(nodeId, name)
- {
- var node = this._idToDOMNode[nodeId];
- if (!node)
- return;
- node._removeAttribute(name);
- this.dispatchEventToListeners(WebInspector.DOMModel.Events.AttrRemoved, { node: node, name: name });
- this._scheduleMutationEvent(node);
- },
-
- /**
- * @param {!Array.<!DOMAgent.NodeId>} nodeIds
- */
- _inlineStyleInvalidated: function(nodeIds)
- {
- for (var i = 0; i < nodeIds.length; ++i)
- this._attributeLoadNodeIds[nodeIds[i]] = true;
- if ("_loadNodeAttributesTimeout" in this)
- return;
- this._loadNodeAttributesTimeout = setTimeout(this._loadNodeAttributes.bind(this), 20);
- },
-
- _loadNodeAttributes: function()
- {
- /**
- * @this {WebInspector.DOMModel}
- * @param {!DOMAgent.NodeId} nodeId
- * @param {?Protocol.Error} error
- * @param {!Array.<string>} attributes
- */
- function callback(nodeId, error, attributes)
- {
- if (error) {
- // We are calling _loadNodeAttributes asynchronously, it is ok if node is not found.
- return;
- }
- var node = this._idToDOMNode[nodeId];
- if (node) {
- if (node._setAttributesPayload(attributes)) {
- this.dispatchEventToListeners(WebInspector.DOMModel.Events.AttrModified, { node: node, name: "style" });
- this._scheduleMutationEvent(node);
- }
- }
- }
-
- delete this._loadNodeAttributesTimeout;
-
- for (var nodeId in this._attributeLoadNodeIds) {
- var nodeIdAsNumber = parseInt(nodeId, 10);
- this._agent.getAttributes(nodeIdAsNumber, callback.bind(this, nodeIdAsNumber));
- }
- this._attributeLoadNodeIds = {};
- },
-
- /**
- * @param {!DOMAgent.NodeId} nodeId
- * @param {string} newValue
- */
- _characterDataModified: function(nodeId, newValue)
- {
- var node = this._idToDOMNode[nodeId];
- node._nodeValue = newValue;
- this.dispatchEventToListeners(WebInspector.DOMModel.Events.CharacterDataModified, node);
- this._scheduleMutationEvent(node);
- },
-
- /**
- * @param {!DOMAgent.NodeId} nodeId
- * @return {?WebInspector.DOMNode}
- */
- nodeForId: function(nodeId)
- {
- return this._idToDOMNode[nodeId] || null;
- },
-
- _documentUpdated: function()
- {
- this._setDocument(null);
- },
-
- /**
- * @param {?DOMAgent.Node} payload
- */
- _setDocument: function(payload)
- {
- this._idToDOMNode = {};
- if (payload && "nodeId" in payload)
- this._document = new WebInspector.DOMDocument(this, payload);
- else
- this._document = null;
- this.dispatchEventToListeners(WebInspector.DOMModel.Events.DocumentUpdated, this._document);
- },
-
- /**
- * @param {!DOMAgent.Node} payload
- */
- _setDetachedRoot: function(payload)
- {
- if (payload.nodeName === "#document")
- new WebInspector.DOMDocument(this, payload);
- else
- WebInspector.DOMNode.create(this, null, false, payload);
- },
-
- /**
- * @param {!DOMAgent.NodeId} parentId
- * @param {!Array.<!DOMAgent.Node>} payloads
- */
- _setChildNodes: function(parentId, payloads)
- {
- if (!parentId && payloads.length) {
- this._setDetachedRoot(payloads[0]);
- return;
- }
-
- var parent = this._idToDOMNode[parentId];
- parent._setChildrenPayload(payloads);
- },
-
- /**
- * @param {!DOMAgent.NodeId} nodeId
- * @param {number} newValue
- */
- _childNodeCountUpdated: function(nodeId, newValue)
- {
- var node = this._idToDOMNode[nodeId];
- node._childNodeCount = newValue;
- this.dispatchEventToListeners(WebInspector.DOMModel.Events.ChildNodeCountUpdated, node);
- this._scheduleMutationEvent(node);
- },
-
- /**
- * @param {!DOMAgent.NodeId} parentId
- * @param {!DOMAgent.NodeId} prevId
- * @param {!DOMAgent.Node} payload
- */
- _childNodeInserted: function(parentId, prevId, payload)
- {
- var parent = this._idToDOMNode[parentId];
- var prev = this._idToDOMNode[prevId];
- var node = parent._insertChild(prev, payload);
- this._idToDOMNode[node.id] = node;
- this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeInserted, node);
- this._scheduleMutationEvent(node);
- },
-
- /**
- * @param {!DOMAgent.NodeId} parentId
- * @param {!DOMAgent.NodeId} nodeId
- */
- _childNodeRemoved: function(parentId, nodeId)
- {
- var parent = this._idToDOMNode[parentId];
- var node = this._idToDOMNode[nodeId];
- parent._removeChild(node);
- this._unbind(node);
- this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeRemoved, {node: node, parent: parent});
- this._scheduleMutationEvent(node);
- },
-
- /**
- * @param {!DOMAgent.NodeId} hostId
- * @param {!DOMAgent.Node} root
- */
- _shadowRootPushed: function(hostId, root)
- {
- var host = this._idToDOMNode[hostId];
- if (!host)
- return;
- var node = WebInspector.DOMNode.create(this, host.ownerDocument, true, root);
- node.parentNode = host;
- this._idToDOMNode[node.id] = node;
- host._shadowRoots.unshift(node);
- this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeInserted, node);
- this._scheduleMutationEvent(node);
- },
-
- /**
- * @param {!DOMAgent.NodeId} hostId
- * @param {!DOMAgent.NodeId} rootId
- */
- _shadowRootPopped: function(hostId, rootId)
- {
- var host = this._idToDOMNode[hostId];
- if (!host)
- return;
- var root = this._idToDOMNode[rootId];
- if (!root)
- return;
- host._removeChild(root);
- this._unbind(root);
- this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeRemoved, {node: root, parent: host});
- this._scheduleMutationEvent(root);
- },
-
- /**
- * @param {!DOMAgent.NodeId} parentId
- * @param {!DOMAgent.Node} pseudoElement
- */
- _pseudoElementAdded: function(parentId, pseudoElement)
- {
- var parent = this._idToDOMNode[parentId];
- if (!parent)
- return;
- var node = WebInspector.DOMNode.create(this, parent.ownerDocument, false, pseudoElement);
- node.parentNode = parent;
- this._idToDOMNode[node.id] = node;
- console.assert(!parent._pseudoElements.get(node.pseudoType()));
- parent._pseudoElements.set(node.pseudoType(), node);
- this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeInserted, node);
- this._scheduleMutationEvent(node);
- },
-
- /**
- * @param {!DOMAgent.NodeId} parentId
- * @param {!DOMAgent.NodeId} pseudoElementId
- */
- _pseudoElementRemoved: function(parentId, pseudoElementId)
- {
- var parent = this._idToDOMNode[parentId];
- if (!parent)
- return;
- var pseudoElement = this._idToDOMNode[pseudoElementId];
- if (!pseudoElement)
- return;
- parent._removeChild(pseudoElement);
- this._unbind(pseudoElement);
- this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeRemoved, {node: pseudoElement, parent: parent});
- this._scheduleMutationEvent(pseudoElement);
- },
-
- /**
- * @param {!DOMAgent.NodeId} insertionPointId
- * @param {!Array.<!DOMAgent.BackendNode>} distributedNodes
- */
- _distributedNodesUpdated: function(insertionPointId, distributedNodes)
- {
- var insertionPoint = this._idToDOMNode[insertionPointId];
- if (!insertionPoint)
- return;
- insertionPoint._setDistributedNodePayloads(distributedNodes);
- this.dispatchEventToListeners(WebInspector.DOMModel.Events.DistributedNodesChanged, insertionPoint);
- this._scheduleMutationEvent(insertionPoint);
- },
-
- /**
- * @param {!WebInspector.DOMNode} node
- */
- _unbind: function(node)
- {
- delete this._idToDOMNode[node.id];
- for (var i = 0; node._children && i < node._children.length; ++i)
- this._unbind(node._children[i]);
- for (var i = 0; i < node._shadowRoots.length; ++i)
- this._unbind(node._shadowRoots[i]);
- var pseudoElements = node.pseudoElements();
- for (var value of pseudoElements.values())
- this._unbind(value);
- if (node._templateContent)
- this._unbind(node._templateContent);
- },
-
- /**
- * @param {!DOMAgent.BackendNodeId} backendNodeId
- */
- _inspectNodeRequested: function(backendNodeId)
- {
- var deferredNode = new WebInspector.DeferredDOMNode(this.target(), backendNodeId);
- this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeInspected, deferredNode);
- },
-
- /**
- * @param {string} query
- * @param {boolean} includeUserAgentShadowDOM
- * @param {function(number)} searchCallback
- */
- performSearch: function(query, includeUserAgentShadowDOM, searchCallback)
- {
- WebInspector.DOMModel.cancelSearch();
-
- /**
- * @param {?Protocol.Error} error
- * @param {string} searchId
- * @param {number} resultsCount
- * @this {WebInspector.DOMModel}
- */
- function callback(error, searchId, resultsCount)
- {
- this._searchId = searchId;
- searchCallback(resultsCount);
- }
- this._agent.performSearch(query, includeUserAgentShadowDOM, callback.bind(this));
- },
-
- /**
- * @param {string} query
- * @param {boolean} includeUserAgentShadowDOM
- * @return {!Promise.<number>}
- */
- performSearchPromise: function(query, includeUserAgentShadowDOM)
- {
- return new Promise(performSearch.bind(this));
-
- /**
- * @param {function(number)} resolve
- * @this {WebInspector.DOMModel}
- */
- function performSearch(resolve)
- {
- this._agent.performSearch(query, includeUserAgentShadowDOM, callback.bind(this));
-
- /**
- * @param {?Protocol.Error} error
- * @param {string} searchId
- * @param {number} resultsCount
- * @this {WebInspector.DOMModel}
- */
- function callback(error, searchId, resultsCount)
- {
- if (!error)
- this._searchId = searchId;
- resolve(error ? 0 : resultsCount);
- }
- }
- },
-
- /**
- * @param {number} index
- * @param {?function(?WebInspector.DOMNode)} callback
- */
- searchResult: function(index, callback)
- {
- if (this._searchId)
- this._agent.getSearchResults(this._searchId, index, index + 1, searchResultsCallback.bind(this));
- else
- callback(null);
-
- /**
- * @param {?Protocol.Error} error
- * @param {!Array.<number>} nodeIds
- * @this {WebInspector.DOMModel}
- */
- function searchResultsCallback(error, nodeIds)
- {
- if (error) {
- console.error(error);
- callback(null);
- return;
- }
- if (nodeIds.length !== 1)
- return;
-
- callback(this.nodeForId(nodeIds[0]));
- }
- },
-
- _cancelSearch: function()
- {
- if (this._searchId) {
- this._agent.discardSearchResults(this._searchId);
- delete this._searchId;
- }
- },
-
- /**
- * @param {!DOMAgent.NodeId} nodeId
- * @return {!Promise<!Array<string>>}
- */
- classNamesPromise: function(nodeId)
- {
- return new Promise(promiseBody.bind(this));
-
- /**
- * @param {function(!Array<string>)} fulfill
- * @this {WebInspector.DOMModel}
- */
- function promiseBody(fulfill)
- {
- this._agent.collectClassNamesFromSubtree(nodeId, classNamesCallback);
-
- /**
- * @param {?string} error
- * @param {?Array<string>} classNames
- */
- function classNamesCallback(error, classNames)
- {
- if (!error && classNames)
- fulfill(classNames);
- else
- fulfill([]);
- }
- }
- },
-
- /**
- * @param {!DOMAgent.NodeId} nodeId
- * @param {string} selectors
- * @param {function(?DOMAgent.NodeId)=} callback
- */
- querySelector: function(nodeId, selectors, callback)
- {
- this._agent.querySelector(nodeId, selectors, this._wrapClientCallback(callback));
- },
-
- /**
- * @param {!DOMAgent.NodeId} nodeId
- * @param {string} selectors
- * @param {function(!Array.<!DOMAgent.NodeId>=)=} callback
- */
- querySelectorAll: function(nodeId, selectors, callback)
- {
- this._agent.querySelectorAll(nodeId, selectors, this._wrapClientCallback(callback));
- },
-
- /**
- * @param {!DOMAgent.NodeId=} nodeId
- * @param {string=} mode
- * @param {!DOMAgent.BackendNodeId=} backendNodeId
- * @param {!RuntimeAgent.RemoteObjectId=} objectId
- */
- highlightDOMNode: function(nodeId, mode, backendNodeId, objectId)
- {
- this.highlightDOMNodeWithConfig(nodeId, { mode: mode }, backendNodeId, objectId);
- },
-
- /**
- * @param {!DOMAgent.NodeId=} nodeId
- * @param {!{mode: (string|undefined), showInfo: (boolean|undefined), selectors: (string|undefined)}=} config
- * @param {!DOMAgent.BackendNodeId=} backendNodeId
- * @param {!RuntimeAgent.RemoteObjectId=} objectId
- */
- highlightDOMNodeWithConfig: function(nodeId, config, backendNodeId, objectId)
- {
- if (WebInspector.DOMModel._highlightDisabled)
- return;
- config = config || { mode: "all", showInfo: undefined, selectors: undefined };
- if (this._hideDOMNodeHighlightTimeout) {
- clearTimeout(this._hideDOMNodeHighlightTimeout);
- delete this._hideDOMNodeHighlightTimeout;
- }
- var highlightConfig = this._buildHighlightConfig(config.mode);
- if (typeof config.showInfo !== "undefined")
- highlightConfig.showInfo = config.showInfo;
- if (typeof config.selectors !== "undefined")
- highlightConfig.selectorList = config.selectors;
- this._highlighter.highlightDOMNode(this.nodeForId(nodeId || 0), highlightConfig, backendNodeId, objectId);
- },
-
- /**
- * @param {!DOMAgent.NodeId} nodeId
- */
- highlightDOMNodeForTwoSeconds: function(nodeId)
- {
- this.highlightDOMNode(nodeId);
- this._hideDOMNodeHighlightTimeout = setTimeout(WebInspector.DOMModel.hideDOMNodeHighlight.bind(WebInspector.DOMModel), 2000);
- },
-
- /**
- * @param {!PageAgent.FrameId} frameId
- */
- highlightFrame: function(frameId)
- {
- if (WebInspector.DOMModel._highlightDisabled)
- return;
- this._highlighter.highlightFrame(frameId);
- },
-
- /**
- * @param {!DOMAgent.InspectMode} mode
- * @param {function(?Protocol.Error)=} callback
- */
- setInspectMode: function(mode, callback)
- {
- /**
- * @this {WebInspector.DOMModel}
- */
- function onDocumentAvailable()
- {
- this._inspectModeEnabled = mode !== DOMAgent.InspectMode.None;
- this.dispatchEventToListeners(WebInspector.DOMModel.Events.InspectModeWillBeToggled, this._inspectModeEnabled);
- this._highlighter.setInspectMode(mode, this._buildHighlightConfig(), callback);
- }
- this.requestDocument(onDocumentAvailable.bind(this));
- },
-
- /**
- * @return {boolean}
- */
- inspectModeEnabled: function()
- {
- return this._inspectModeEnabled;
- },
-
- /**
- * @param {string=} mode
- * @return {!DOMAgent.HighlightConfig}
- */
- _buildHighlightConfig: function(mode)
- {
- mode = mode || "all";
- var showRulers = WebInspector.moduleSetting("showMetricsRulers").get();
- var highlightConfig = { showInfo: mode === "all", showRulers: showRulers, showExtensionLines: showRulers };
- if (mode === "all" || mode === "content")
- highlightConfig.contentColor = WebInspector.Color.PageHighlight.Content.toProtocolRGBA();
-
- if (mode === "all" || mode === "padding")
- highlightConfig.paddingColor = WebInspector.Color.PageHighlight.Padding.toProtocolRGBA();
-
- if (mode === "all" || mode === "border")
- highlightConfig.borderColor = WebInspector.Color.PageHighlight.Border.toProtocolRGBA();
-
- if (mode === "all" || mode === "margin")
- highlightConfig.marginColor = WebInspector.Color.PageHighlight.Margin.toProtocolRGBA();
-
- if (mode === "all") {
- highlightConfig.eventTargetColor = WebInspector.Color.PageHighlight.EventTarget.toProtocolRGBA();
- highlightConfig.shapeColor = WebInspector.Color.PageHighlight.Shape.toProtocolRGBA();
- highlightConfig.shapeMarginColor = WebInspector.Color.PageHighlight.ShapeMargin.toProtocolRGBA();
- highlightConfig.displayAsMaterial = Runtime.experiments.isEnabled("inspectTooltip");
- }
- return highlightConfig;
- },
-
- /**
- * @param {!WebInspector.DOMNode} node
- * @param {function(?Protocol.Error, ...)=} callback
- * @return {function(...)}
- * @template T
- */
- _markRevision: function(node, callback)
- {
- /**
- * @param {?Protocol.Error} error
- * @this {WebInspector.DOMModel}
- */
- function wrapperFunction(error)
- {
- if (!error)
- this.markUndoableState();
-
- if (callback)
- callback.apply(this, arguments);
- }
- return wrapperFunction.bind(this);
- },
-
- markUndoableState: function()
- {
- this._agent.markUndoableState();
- },
-
- /**
- * @param {function(?Protocol.Error)=} callback
- */
- undo: function(callback)
- {
- /**
- * @param {?Protocol.Error} error
- * @this {WebInspector.DOMModel}
- */
- function mycallback(error)
- {
- this.dispatchEventToListeners(WebInspector.DOMModel.Events.UndoRedoCompleted);
- callback(error);
- }
-
- this.dispatchEventToListeners(WebInspector.DOMModel.Events.UndoRedoRequested);
- this._agent.undo(callback);
- },
-
- /**
- * @param {function(?Protocol.Error)=} callback
- */
- redo: function(callback)
- {
- /**
- * @param {?Protocol.Error} error
- * @this {WebInspector.DOMModel}
- */
- function mycallback(error)
- {
- this.dispatchEventToListeners(WebInspector.DOMModel.Events.UndoRedoCompleted);
- callback(error);
- }
-
- this.dispatchEventToListeners(WebInspector.DOMModel.Events.UndoRedoRequested);
- this._agent.redo(callback);
- },
-
- /**
- * @param {?WebInspector.DOMNodeHighlighter} highlighter
- */
- setHighlighter: function(highlighter)
- {
- this._highlighter = highlighter || this._defaultHighlighter;
- },
-
- /**
- * @param {number} x
- * @param {number} y
- * @param {function(?WebInspector.DOMNode)} callback
- */
- nodeForLocation: function(x, y, callback)
- {
- this._agent.getNodeForLocation(x, y, mycallback.bind(this));
-
- /**
- * @param {?Protocol.Error} error
- * @param {number} nodeId
- * @this {WebInspector.DOMModel}
- */
- function mycallback(error, nodeId)
- {
- if (error) {
- callback(null);
- return;
- }
- callback(this.nodeForId(nodeId));
- }
- },
-
- /**
- * @param {!WebInspector.RemoteObject} object
- * @param {function(?WebInspector.DOMNode)} callback
- */
- pushObjectAsNodeToFrontend: function(object, callback)
- {
- if (object.isNode())
- this.pushNodeToFrontend(object.objectId, callback);
- else
- callback(null);
- },
-
- /**
- * @override
- * @return {!Promise}
- */
- suspendModel: function()
- {
- return new Promise(promiseBody.bind(this));
-
- /**
- * @param {function()} fulfill
- * @this {WebInspector.DOMModel}
- */
- function promiseBody(fulfill)
- {
- this._agent.disable(callback.bind(this));
-
- /**
- * @this {WebInspector.DOMModel}
- */
- function callback()
- {
- this._setDocument(null);
- fulfill();
- }
- }
- },
-
- /**
- * @override
- * @return {!Promise}
- */
- resumeModel: function()
- {
- return new Promise(promiseBody.bind(this));
-
- /**
- * @param {function()} fulfill
- * @this {WebInspector.DOMModel}
- */
- function promiseBody(fulfill)
- {
- this._agent.enable(fulfill);
- }
- },
-
- /**
- * @param {!DOMAgent.NodeId} nodeId
- */
- nodeHighlightRequested: function(nodeId)
- {
- var node = this.nodeForId(nodeId);
- if (!node)
- return;
-
- this.dispatchEventToListeners(WebInspector.DOMModel.Events.NodeHighlightedInOverlay, node);
- },
-
- __proto__: WebInspector.SDKModel.prototype
-};
-
-/**
- * @constructor
- * @implements {DOMAgent.Dispatcher}
- * @param {!WebInspector.DOMModel} domModel
- */
-WebInspector.DOMDispatcher = function(domModel)
-{
- this._domModel = domModel;
-};
-
-WebInspector.DOMDispatcher.prototype = {
- /**
- * @override
- */
- documentUpdated: function()
- {
- this._domModel._documentUpdated();
- },
-
- /**
- * @override
- * @param {!DOMAgent.NodeId} nodeId
- */
- inspectNodeRequested: function(nodeId)
- {
- this._domModel._inspectNodeRequested(nodeId);
- },
-
- /**
- * @override
- * @param {!DOMAgent.NodeId} nodeId
- * @param {string} name
- * @param {string} value
- */
- attributeModified: function(nodeId, name, value)
- {
- this._domModel._attributeModified(nodeId, name, value);
- },
-
- /**
- * @override
- * @param {!DOMAgent.NodeId} nodeId
- * @param {string} name
- */
- attributeRemoved: function(nodeId, name)
- {
- this._domModel._attributeRemoved(nodeId, name);
- },
-
- /**
- * @override
- * @param {!Array.<!DOMAgent.NodeId>} nodeIds
- */
- inlineStyleInvalidated: function(nodeIds)
- {
- this._domModel._inlineStyleInvalidated(nodeIds);
- },
-
- /**
- * @override
- * @param {!DOMAgent.NodeId} nodeId
- * @param {string} characterData
- */
- characterDataModified: function(nodeId, characterData)
- {
- this._domModel._characterDataModified(nodeId, characterData);
- },
-
- /**
- * @override
- * @param {!DOMAgent.NodeId} parentId
- * @param {!Array.<!DOMAgent.Node>} payloads
- */
- setChildNodes: function(parentId, payloads)
- {
- this._domModel._setChildNodes(parentId, payloads);
- },
-
- /**
- * @override
- * @param {!DOMAgent.NodeId} nodeId
- * @param {number} childNodeCount
- */
- childNodeCountUpdated: function(nodeId, childNodeCount)
- {
- this._domModel._childNodeCountUpdated(nodeId, childNodeCount);
- },
-
- /**
- * @override
- * @param {!DOMAgent.NodeId} parentNodeId
- * @param {!DOMAgent.NodeId} previousNodeId
- * @param {!DOMAgent.Node} payload
- */
- childNodeInserted: function(parentNodeId, previousNodeId, payload)
- {
- this._domModel._childNodeInserted(parentNodeId, previousNodeId, payload);
- },
-
- /**
- * @override
- * @param {!DOMAgent.NodeId} parentNodeId
- * @param {!DOMAgent.NodeId} nodeId
- */
- childNodeRemoved: function(parentNodeId, nodeId)
- {
- this._domModel._childNodeRemoved(parentNodeId, nodeId);
- },
-
- /**
- * @override
- * @param {!DOMAgent.NodeId} hostId
- * @param {!DOMAgent.Node} root
- */
- shadowRootPushed: function(hostId, root)
- {
- this._domModel._shadowRootPushed(hostId, root);
- },
-
- /**
- * @override
- * @param {!DOMAgent.NodeId} hostId
- * @param {!DOMAgent.NodeId} rootId
- */
- shadowRootPopped: function(hostId, rootId)
- {
- this._domModel._shadowRootPopped(hostId, rootId);
- },
-
- /**
- * @override
- * @param {!DOMAgent.NodeId} parentId
- * @param {!DOMAgent.Node} pseudoElement
- */
- pseudoElementAdded: function(parentId, pseudoElement)
- {
- this._domModel._pseudoElementAdded(parentId, pseudoElement);
- },
-
- /**
- * @override
- * @param {!DOMAgent.NodeId} parentId
- * @param {!DOMAgent.NodeId} pseudoElementId
- */
- pseudoElementRemoved: function(parentId, pseudoElementId)
- {
- this._domModel._pseudoElementRemoved(parentId, pseudoElementId);
- },
-
- /**
- * @override
- * @param {!DOMAgent.NodeId} insertionPointId
- * @param {!Array.<!DOMAgent.BackendNode>} distributedNodes
- */
- distributedNodesUpdated: function(insertionPointId, distributedNodes)
- {
- this._domModel._distributedNodesUpdated(insertionPointId, distributedNodes);
- },
-
- /**
- * @override
- * @param {!DOMAgent.NodeId} nodeId
- */
- nodeHighlightRequested: function(nodeId)
- {
- this._domModel.nodeHighlightRequested(nodeId);
- }
-};
-
-/**
- * @interface
- */
-WebInspector.DOMNodeHighlighter = function() {
-};
-
-WebInspector.DOMNodeHighlighter.prototype = {
- /**
- * @param {?WebInspector.DOMNode} node
- * @param {!DOMAgent.HighlightConfig} config
- * @param {!DOMAgent.BackendNodeId=} backendNodeId
- * @param {!RuntimeAgent.RemoteObjectId=} objectId
- */
- highlightDOMNode: function(node, config, backendNodeId, objectId) {},
-
- /**
- * @param {!DOMAgent.InspectMode} mode
- * @param {!DOMAgent.HighlightConfig} config
- * @param {function(?Protocol.Error)=} callback
- */
- setInspectMode: function(mode, config, callback) {},
-
- /**
- * @param {!PageAgent.FrameId} frameId
- */
- highlightFrame: function(frameId) {}
-};
-
-/**
- * @constructor
- * @implements {WebInspector.DOMNodeHighlighter}
- * @param {!Protocol.DOMAgent} agent
- */
-WebInspector.DefaultDOMNodeHighlighter = function(agent)
-{
- this._agent = agent;
-};
-
-WebInspector.DefaultDOMNodeHighlighter.prototype = {
- /**
- * @override
- * @param {?WebInspector.DOMNode} node
- * @param {!DOMAgent.HighlightConfig} config
- * @param {!DOMAgent.BackendNodeId=} backendNodeId
- * @param {!RuntimeAgent.RemoteObjectId=} objectId
- */
- highlightDOMNode: function(node, config, backendNodeId, objectId)
- {
- if (objectId || node || backendNodeId)
- this._agent.highlightNode(config, (objectId || backendNodeId) ? undefined : node.id, backendNodeId, objectId);
- else
- this._agent.hideHighlight();
- },
-
- /**
- * @override
- * @param {!DOMAgent.InspectMode} mode
- * @param {!DOMAgent.HighlightConfig} config
- * @param {function(?Protocol.Error)=} callback
- */
- setInspectMode: function(mode, config, callback)
- {
- this._agent.setInspectMode(mode, config, callback);
- },
-
- /**
- * @override
- * @param {!PageAgent.FrameId} frameId
- */
- highlightFrame: function(frameId)
- {
- this._agent.highlightFrame(frameId, WebInspector.Color.PageHighlight.Content.toProtocolRGBA(), WebInspector.Color.PageHighlight.ContentOutline.toProtocolRGBA());
- }
-};
-
-/**
- * @param {!WebInspector.Target} target
- * @return {?WebInspector.DOMModel}
- */
-WebInspector.DOMModel.fromTarget = function(target)
-{
- return /** @type {?WebInspector.DOMModel} */ (target.model(WebInspector.DOMModel));
-};

Powered by Google App Engine
This is Rietveld 408576698