| Index: sky/framework/inspector/dom-agent.sky
|
| diff --git a/sky/framework/inspector/dom-agent.sky b/sky/framework/inspector/dom-agent.sky
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..6e6048fda614c2a62a912f3ff7e9ac33bf03f026
|
| --- /dev/null
|
| +++ b/sky/framework/inspector/dom-agent.sky
|
| @@ -0,0 +1,169 @@
|
| +<script>
|
| +function DOMAgent(delegate) {
|
| + this.enabled = false;
|
| + this.delegate_ = delegate;
|
| + this.nextNodeId_ = 1;
|
| + this.nodeToId_ = new Map();
|
| + this.idToNode_ = new Map();
|
| +}
|
| +
|
| +DOMAgent.prototype.getIdForNode_ = function(node) {
|
| + if (this.nodeToId_.has(node))
|
| + return this.nodeToId_.get(node);
|
| + var id = this.nextNodeId_++;
|
| + this.nodeToId_.set(node, id);
|
| + this.idToNode_.set(id, node);
|
| + return id;
|
| +};
|
| +
|
| +DOMAgent.prototype.serializeChildren_ = function(node) {
|
| + var children = [];
|
| + for (var child = node.firstChild; child; child = child.nextSibling) {
|
| + var record = this.serializeNode_(child);
|
| + if (record)
|
| + children.push(record);
|
| + }
|
| + return children;
|
| +};
|
| +
|
| +DOMAgent.prototype.serializeAttributes_ = function(element) {
|
| + var attributes = [];
|
| + var attrs = element.attributes;
|
| + for (var i = 0; i < attrs.length; ++i) {
|
| + var attr = attrs[i];
|
| + attributes.push(attr.name);
|
| + attributes.push(attr.value);
|
| + }
|
| + return attributes;
|
| +};
|
| +
|
| +DOMAgent.prototype.serializeNode_ = function(node) {
|
| + var id = this.getIdForNode_(node);
|
| +
|
| + var record = {
|
| + nodeId: id,
|
| + };
|
| +
|
| + var isContainer = false;
|
| +
|
| + if (node instanceof Element) {
|
| + isContainer = true;
|
| + record.nodeType = 1;
|
| + record.nodeName = node.tagName;
|
| + record.localName = node.tagName;
|
| + record.nodeValue = "";
|
| + record.attributes = this.serializeAttributes_(node);
|
| + } else if (node instanceof Text) {
|
| + record.nodeType = 3;
|
| + record.nodeName = "#text";
|
| + var nodeValue = node.data;
|
| + if (!nodeValue.trim())
|
| + return null;
|
| + record.nodeValue = nodeValue;
|
| + } else if (node instanceof Comment) {
|
| + record.nodeType = 8;
|
| + record.nodeName = "#comment";
|
| + record.nodeValue = node.data;
|
| + } else if (node instanceof Document) {
|
| + isContainer = true;
|
| + record.nodeType = 9;
|
| + record.nodeName = "#document";
|
| + record.localName = "";
|
| + record.nodeValue = "";
|
| + record.documentURL = node.URL;
|
| + record.baseURL = node.baseURI;
|
| + } else if (node instanceof DocumentFragment) {
|
| + isContainer = true;
|
| + record.nodeType = 11;
|
| + record.nodeName = "#document-fragment";
|
| + record.localName = "";
|
| + record.nodeValue = "";
|
| + } else {
|
| + console.log("Unknown node type");
|
| + return null;
|
| + }
|
| +
|
| + if (isContainer) {
|
| + var children = this.serializeChildren_(node);
|
| + if (children.length) {
|
| + record.childNodeCount = children.length;
|
| + record.children = children;
|
| + }
|
| + }
|
| +
|
| + return record;
|
| +};
|
| +
|
| +DOMAgent.prototype.enable = function() {
|
| + this.enabled = true;
|
| + this.observer_ = new MutationObserver(this.mutationCallback_.bind(this));
|
| + this.observer_.observe(document, {
|
| + childList: true,
|
| + attributes: true,
|
| + characterData: true,
|
| + subtree : true,
|
| + });
|
| +};
|
| +
|
| +DOMAgent.prototype.getDocument = function() {
|
| + return {
|
| + root: this.serializeNode_(document),
|
| + };
|
| +};
|
| +
|
| +DOMAgent.prototype.hideHighlight = function() {
|
| +};
|
| +
|
| +DOMAgent.prototype.highlightNode = function() {
|
| +};
|
| +
|
| +DOMAgent.prototype.mutationCallback_ = function(mutationRecords) {
|
| + for (var i = 0; i < mutationRecords.length; ++i) {
|
| + var record = mutationRecords[i];
|
| + var type = record.type;
|
| + var target = record.target;
|
| + var nodeId = this.getIdForNode_(target);
|
| + if (type == "attributes") {
|
| + var attributeName = record.attributeName;
|
| + if (target.hasAttribute(attributeName)) {
|
| + this.delegate_.sendMessage("DOM.attributeModified", {
|
| + nodeId: nodeId,
|
| + name: attributeName,
|
| + value: target.getAttribute(attributeName),
|
| + });
|
| + } else {
|
| + this.delegate_.sendMessage("DOM.attributeRemoved", {
|
| + nodeId: nodeId,
|
| + name: attributeName,
|
| + });
|
| + }
|
| + } else if (type == "characterData") {
|
| + this.delegate_.sendMessage("DOM.characterDataModified", {
|
| + nodeId: nodeId,
|
| + characterData: target.data,
|
| + });
|
| + } else if (type == "childList") {
|
| + // FIXME: If this subtree isn't expanded, we only need to send across the
|
| + // {"method":"DOM.childNodeCountUpdated","params":"nodeId":648,"childNodeCount":2}
|
| +
|
| + Array.prototype.forEach.call(record.removedNodes, function(node) {
|
| + this.delegate_.sendMessage("DOM.childNodeRemoved", {
|
| + parentNodeId: nodeId,
|
| + nodeId: this.getIdForNode_(node),
|
| + });
|
| + }.bind(this));
|
| +
|
| + Array.prototype.forEach.call(record.addedNodes, function(node) {
|
| + var previousNodeId = node.previousSibling ? this.getIdForNode_(node.previousSibling) : 0;
|
| + this.delegate_.sendMessage("DOM.childNodeInserted", {
|
| + parentNodeId: nodeId,
|
| + previousNodeId: previousNodeId,
|
| + node: this.serializeNode_(node),
|
| + });
|
| + }.bind(this));
|
| + }
|
| + }
|
| +};
|
| +
|
| +this.exports = DOMAgent;
|
| +</script>
|
|
|