DOMModel.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. export class DOMNode{constructor(domModel){this._domModel=domModel;}
  2. static create(domModel,doc,isInShadowTree,payload){const node=new SDK.DOMNode(domModel);node._init(doc,isInShadowTree,payload);return node;}
  3. _init(doc,isInShadowTree,payload){this._agent=this._domModel._agent;this.ownerDocument=doc;this._isInShadowTree=isInShadowTree;this.id=payload.nodeId;this._backendNodeId=payload.backendNodeId;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._isSVGNode=!!payload.isSVG;this._creationStackTrace=null;this._shadowRoots=[];this._attributes=[];this._attributesMap={};if(payload.attributes){this._setAttributesPayload(payload.attributes);}
  4. 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(let i=0;i<payload.shadowRoots.length;++i){const root=payload.shadowRoots[i];const node=SDK.DOMNode.create(this._domModel,this.ownerDocument,true,root);this._shadowRoots.push(node);node.parentNode=this;}}
  5. if(payload.templateContent){this._templateContent=SDK.DOMNode.create(this._domModel,this.ownerDocument,true,payload.templateContent);this._templateContent.parentNode=this;this._children=[];}
  6. if(payload.contentDocument){this._contentDocument=new DOMDocument(this._domModel,payload.contentDocument);this._contentDocument.parentNode=this;this._children=[];}else if((payload.nodeName==='IFRAME'||payload.nodeName==='PORTAL')&&payload.frameId){const childTarget=SDK.targetManager.targetById(payload.frameId);const childModel=childTarget?childTarget.model(DOMModel):null;if(childModel){this._childDocumentPromiseForTesting=childModel.requestDocument();}
  7. this._children=[];}
  8. if(payload.importedDocument){this._importedDocument=SDK.DOMNode.create(this._domModel,this.ownerDocument,true,payload.importedDocument);this._importedDocument.parentNode=this;this._children=[];}
  9. if(payload.distributedNodes){this._setDistributedNodePayloads(payload.distributedNodes);}
  10. if(payload.children){this._setChildrenPayload(payload.children);}
  11. this._setPseudoElements(payload.pseudoElements);if(this._nodeType===Node.ELEMENT_NODE){if(this.ownerDocument&&!this.ownerDocument.documentElement&&this._nodeName==='HTML'){this.ownerDocument.documentElement=this;}
  12. 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;}}
  13. isSVGNode(){return this._isSVGNode;}
  14. creationStackTrace(){if(this._creationStackTrace){return this._creationStackTrace;}
  15. const stackTracesPromise=this._agent.invoke_getNodeStackTraces({nodeId:this.id});this._creationStackTrace=stackTracesPromise.then(res=>res.creation);return this._creationStackTrace;}
  16. domModel(){return this._domModel;}
  17. backendNodeId(){return this._backendNodeId;}
  18. children(){return this._children?this._children.slice():null;}
  19. hasAttributes(){return this._attributes.length>0;}
  20. childNodeCount(){return this._childNodeCount;}
  21. hasShadowRoots(){return!!this._shadowRoots.length;}
  22. shadowRoots(){return this._shadowRoots.slice();}
  23. templateContent(){return this._templateContent||null;}
  24. contentDocument(){return this._contentDocument||null;}
  25. isIframe(){return this._nodeName==='IFRAME';}
  26. isPortal(){return this._nodeName==='PORTAL';}
  27. importedDocument(){return this._importedDocument||null;}
  28. nodeType(){return this._nodeType;}
  29. nodeName(){return this._nodeName;}
  30. pseudoType(){return this._pseudoType;}
  31. hasPseudoElements(){return this._pseudoElements.size>0;}
  32. pseudoElements(){return this._pseudoElements;}
  33. beforePseudoElement(){if(!this._pseudoElements){return null;}
  34. return this._pseudoElements.get(SDK.DOMNode.PseudoElementNames.Before);}
  35. afterPseudoElement(){if(!this._pseudoElements){return null;}
  36. return this._pseudoElements.get(SDK.DOMNode.PseudoElementNames.After);}
  37. markerPseudoElement(){if(!this._pseudoElements){return null;}
  38. return this._pseudoElements.get(SDK.DOMNode.PseudoElementNames.Marker);}
  39. isInsertionPoint(){return!this.isXMLNode()&&(this._nodeName==='SHADOW'||this._nodeName==='CONTENT'||this._nodeName==='SLOT');}
  40. distributedNodes(){return this._distributedNodes||[];}
  41. isInShadowTree(){return this._isInShadowTree;}
  42. ancestorShadowHost(){const ancestorShadowRoot=this.ancestorShadowRoot();return ancestorShadowRoot?ancestorShadowRoot.parentNode:null;}
  43. ancestorShadowRoot(){if(!this._isInShadowTree){return null;}
  44. let current=this;while(current&&!current.isShadowRoot()){current=current.parentNode;}
  45. return current;}
  46. ancestorUserAgentShadowRoot(){const ancestorShadowRoot=this.ancestorShadowRoot();if(!ancestorShadowRoot){return null;}
  47. return ancestorShadowRoot.shadowRootType()===SDK.DOMNode.ShadowRootTypes.UserAgent?ancestorShadowRoot:null;}
  48. isShadowRoot(){return!!this._shadowRootType;}
  49. shadowRootType(){return this._shadowRootType||null;}
  50. nodeNameInCorrectCase(){const shadowRootType=this.shadowRootType();if(shadowRootType){return'#shadow-root ('+shadowRootType+')';}
  51. if(!this.localName()){return this.nodeName();}
  52. if(this.localName().length!==this.nodeName().length){return this.nodeName();}
  53. return this.localName();}
  54. setNodeName(name,callback){this._agent.invoke_setNodeName({nodeId:this.id,name}).then(response=>{if(!response[Protocol.Error]){this._domModel.markUndoableState();}
  55. if(callback){callback(response[Protocol.Error]||null,this._domModel.nodeForId(response.nodeId));}});}
  56. localName(){return this._localName;}
  57. nodeValue(){return this._nodeValue;}
  58. setNodeValue(value,callback){this._agent.invoke_setNodeValue({nodeId:this.id,value}).then(response=>{if(!response[Protocol.Error]){this._domModel.markUndoableState();}
  59. if(callback){callback(response[Protocol.Error]||null);}});}
  60. getAttribute(name){const attr=this._attributesMap[name];return attr?attr.value:undefined;}
  61. setAttribute(name,text,callback){this._agent.invoke_setAttributesAsText({nodeId:this.id,text,name}).then(response=>{if(!response[Protocol.Error]){this._domModel.markUndoableState();}
  62. if(callback){callback(response[Protocol.Error]||null);}});}
  63. setAttributeValue(name,value,callback){this._agent.invoke_setAttributeValue({nodeId:this.id,name,value}).then(response=>{if(!response[Protocol.Error]){this._domModel.markUndoableState();}
  64. if(callback){callback(response[Protocol.Error]||null);}});}
  65. setAttributeValuePromise(name,value){return new Promise(fulfill=>this.setAttributeValue(name,value,fulfill));}
  66. attributes(){return this._attributes;}
  67. async removeAttribute(name){const response=await this._agent.invoke_removeAttribute({nodeId:this.id,name});if(response[Protocol.Error]){return;}
  68. delete this._attributesMap[name];const index=this._attributes.findIndex(attr=>attr.name===name);if(index!==-1){this._attributes.splice(index,1);}
  69. this._domModel.markUndoableState();}
  70. getChildNodes(callback){if(this._children){callback(this.children());return;}
  71. this._agent.invoke_requestChildNodes({nodeId:this.id}).then(response=>{callback(response[Protocol.Error]?null:this.children());});}
  72. async getSubtree(depth,pierce){const response=await this._agent.invoke_requestChildNodes({nodeId:this.id,depth:depth,pierce:pierce});return response[Protocol.Error]?null:this._children;}
  73. getOuterHTML(){return this._agent.getOuterHTML(this.id);}
  74. setOuterHTML(html,callback){this._agent.invoke_setOuterHTML({nodeId:this.id,outerHTML:html}).then(response=>{if(!response[Protocol.Error]){this._domModel.markUndoableState();}
  75. if(callback){callback(response[Protocol.Error]||null);}});}
  76. removeNode(callback){this._agent.invoke_removeNode({nodeId:this.id}).then(response=>{if(!response[Protocol.Error]){this._domModel.markUndoableState();}
  77. if(callback){callback(response[Protocol.Error]||null);}});}
  78. async copyNode(){const text=await this._agent.getOuterHTML(this.id);if(text!==null){Host.InspectorFrontendHost.copyText(text);}
  79. return text;}
  80. path(){function canPush(node){return node&&('index'in node||(node.isShadowRoot()&&node.parentNode))&&node._nodeName.length;}
  81. const path=[];let node=this;while(canPush(node)){const index=typeof node.index==='number'?node.index:(node.shadowRootType()===SDK.DOMNode.ShadowRootTypes.UserAgent?'u':'a');path.push([index,node._nodeName]);node=node.parentNode;}
  82. path.reverse();return path.join(',');}
  83. isAncestor(node){if(!node){return false;}
  84. let currentNode=node.parentNode;while(currentNode){if(this===currentNode){return true;}
  85. currentNode=currentNode.parentNode;}
  86. return false;}
  87. isDescendant(descendant){return descendant!==null&&descendant.isAncestor(this);}
  88. frameId(){let node=this.parentNode||this;while(!node._frameOwnerFrameId&&node.parentNode){node=node.parentNode;}
  89. return node._frameOwnerFrameId;}
  90. _setAttributesPayload(attrs){let attributesChanged=!this._attributes||attrs.length!==this._attributes.length*2;const oldAttributesMap=this._attributesMap||{};this._attributes=[];this._attributesMap={};for(let i=0;i<attrs.length;i+=2){const name=attrs[i];const value=attrs[i+1];this._addAttribute(name,value);if(attributesChanged){continue;}
  91. if(!oldAttributesMap[name]||oldAttributesMap[name].value!==value){attributesChanged=true;}}
  92. return attributesChanged;}
  93. _insertChild(prev,payload){const node=SDK.DOMNode.create(this._domModel,this.ownerDocument,this._isInShadowTree,payload);this._children.splice(this._children.indexOf(prev)+1,0,node);this._renumber();return node;}
  94. _removeChild(node){if(node.pseudoType()){this._pseudoElements.delete(node.pseudoType());}else{const 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);}}
  95. node.parentNode=null;this._subtreeMarkerCount-=node._subtreeMarkerCount;if(node._subtreeMarkerCount){this._domModel.dispatchEventToListeners(Events.MarkersChanged,this);}
  96. this._renumber();}
  97. _setChildrenPayload(payloads){this._children=[];for(let i=0;i<payloads.length;++i){const payload=payloads[i];const node=SDK.DOMNode.create(this._domModel,this.ownerDocument,this._isInShadowTree,payload);this._children.push(node);}
  98. this._renumber();}
  99. _setPseudoElements(payloads){this._pseudoElements=new Map();if(!payloads){return;}
  100. for(let i=0;i<payloads.length;++i){const node=SDK.DOMNode.create(this._domModel,this.ownerDocument,this._isInShadowTree,payloads[i]);node.parentNode=this;this._pseudoElements.set(node.pseudoType(),node);}}
  101. _setDistributedNodePayloads(payloads){this._distributedNodes=[];for(const payload of payloads){this._distributedNodes.push(new DOMNodeShortcut(this._domModel.target(),payload.backendNodeId,payload.nodeType,payload.nodeName));}}
  102. _renumber(){this._childNodeCount=this._children.length;if(this._childNodeCount===0){this.firstChild=null;this.lastChild=null;return;}
  103. this.firstChild=this._children[0];this.lastChild=this._children[this._childNodeCount-1];for(let i=0;i<this._childNodeCount;++i){const 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;}}
  104. _addAttribute(name,value){const attr={name:name,value:value,_node:this};this._attributesMap[name]=attr;this._attributes.push(attr);}
  105. _setAttribute(name,value){const attr=this._attributesMap[name];if(attr){attr.value=value;}else{this._addAttribute(name,value);}}
  106. _removeAttribute(name){const attr=this._attributesMap[name];if(attr){this._attributes.remove(attr);delete this._attributesMap[name];}}
  107. copyTo(targetNode,anchorNode,callback){this._agent.invoke_copyTo({nodeId:this.id,targetNodeId:targetNode.id,insertBeforeNodeId:anchorNode?anchorNode.id:undefined}).then(response=>{if(!response[Protocol.Error]){this._domModel.markUndoableState();}
  108. if(callback){callback(response[Protocol.Error]||null,response.nodeId);}});}
  109. moveTo(targetNode,anchorNode,callback){this._agent.invoke_moveTo({nodeId:this.id,targetNodeId:targetNode.id,insertBeforeNodeId:anchorNode?anchorNode.id:undefined}).then(response=>{if(!response[Protocol.Error]){this._domModel.markUndoableState();}
  110. if(callback){callback(response[Protocol.Error]||null,this._domModel.nodeForId(response.nodeId));}});}
  111. isXMLNode(){return!!this._xmlVersion;}
  112. setMarker(name,value){if(value===null){if(!this._markers.has(name)){return;}
  113. this._markers.delete(name);for(let node=this;node;node=node.parentNode){--node._subtreeMarkerCount;}
  114. for(let node=this;node;node=node.parentNode){this._domModel.dispatchEventToListeners(Events.MarkersChanged,node);}
  115. return;}
  116. if(this.parentNode&&!this._markers.has(name)){for(let node=this;node;node=node.parentNode){++node._subtreeMarkerCount;}}
  117. this._markers.set(name,value);for(let node=this;node;node=node.parentNode){this._domModel.dispatchEventToListeners(Events.MarkersChanged,node);}}
  118. marker(name){return this._markers.get(name)||null;}
  119. traverseMarkers(visitor){function traverse(node){if(!node._subtreeMarkerCount){return;}
  120. for(const marker of node._markers.keys()){visitor(node,marker);}
  121. if(!node._children){return;}
  122. for(const child of node._children){traverse(child);}}
  123. traverse(this);}
  124. resolveURL(url){if(!url){return url;}
  125. for(let frameOwnerCandidate=this;frameOwnerCandidate;frameOwnerCandidate=frameOwnerCandidate.parentNode){if(frameOwnerCandidate.baseURL){return Common.ParsedURL.completeURL(frameOwnerCandidate.baseURL,url);}}
  126. return null;}
  127. highlight(mode){this._domModel.overlayModel().highlightInOverlay({node:this},mode);}
  128. highlightForTwoSeconds(){this._domModel.overlayModel().highlightInOverlayForTwoSeconds({node:this});}
  129. async resolveToObject(objectGroup){const object=await this._agent.resolveNode(this.id,undefined,objectGroup);return object&&this._domModel._runtimeModel.createRemoteObject(object);}
  130. boxModel(){return this._agent.getBoxModel(this.id);}
  131. setAsInspectedNode(){let node=this;while(true){let ancestor=node.ancestorUserAgentShadowRoot();if(!ancestor){break;}
  132. ancestor=node.ancestorShadowHost();if(!ancestor){break;}
  133. node=ancestor;}
  134. this._agent.setInspectedNode(node.id);}
  135. enclosingElementOrSelf(){let node=this;if(node&&node.nodeType()===Node.TEXT_NODE&&node.parentNode){node=node.parentNode;}
  136. if(node&&node.nodeType()!==Node.ELEMENT_NODE){node=null;}
  137. return node;}
  138. async scrollIntoView(){const node=this.enclosingElementOrSelf();if(!node){return;}
  139. const object=await node.resolveToObject();if(!object){return;}
  140. object.callFunction(scrollIntoView);object.release();node.highlightForTwoSeconds();function scrollIntoView(){this.scrollIntoViewIfNeeded(true);}}
  141. async focus(){const node=this.enclosingElementOrSelf();const object=await node.resolveToObject();if(!object){return;}
  142. await object.callFunction(focusInPage);object.release();node.highlightForTwoSeconds();this._domModel.target().pageAgent().bringToFront();function focusInPage(){this.focus();}}
  143. simpleSelector(){const lowerCaseName=this.localName()||this.nodeName().toLowerCase();if(this.nodeType()!==Node.ELEMENT_NODE){return lowerCaseName;}
  144. if(lowerCaseName==='input'&&this.getAttribute('type')&&!this.getAttribute('id')&&!this.getAttribute('class')){return lowerCaseName+'[type="'+this.getAttribute('type')+'"]';}
  145. if(this.getAttribute('id')){return lowerCaseName+'#'+this.getAttribute('id');}
  146. if(this.getAttribute('class')){return(lowerCaseName==='div'?'':lowerCaseName)+'.'+
  147. this.getAttribute('class').trim().replace(/\s+/g,'.');}
  148. return lowerCaseName;}}
  149. DOMNode.PseudoElementNames={Before:'before',After:'after',Marker:'marker'};DOMNode.ShadowRootTypes={UserAgent:'user-agent',Open:'open',Closed:'closed'};export class DeferredDOMNode{constructor(target,backendNodeId){this._domModel=(target.model(DOMModel));this._backendNodeId=backendNodeId;}
  150. resolve(callback){this.resolvePromise().then(callback);}
  151. async resolvePromise(){const nodeIds=await this._domModel.pushNodesByBackendIdsToFrontend(new Set([this._backendNodeId]));return nodeIds&&nodeIds.get(this._backendNodeId)||null;}
  152. backendNodeId(){return this._backendNodeId;}
  153. domModel(){return this._domModel;}
  154. highlight(){this._domModel.overlayModel().highlightInOverlay({deferredNode:this});}}
  155. export class DOMNodeShortcut{constructor(target,backendNodeId,nodeType,nodeName){this.nodeType=nodeType;this.nodeName=nodeName;this.deferredNode=new SDK.DeferredDOMNode(target,backendNodeId);}}
  156. export class DOMDocument extends DOMNode{constructor(domModel,payload){super(domModel);this._init(this,false,payload);this.documentURL=payload.documentURL||'';this.baseURL=payload.baseURL||'';}}
  157. export default class DOMModel extends SDK.SDKModel{constructor(target){super(target);this._agent=target.domAgent();this._idToDOMNode={};this._document=null;this._attributeLoadNodeIds=new Set();target.registerDOMDispatcher(new DOMDispatcher(this));this._runtimeModel=(target.model(SDK.RuntimeModel));if(!target.suspended()){this._agent.enable();}
  158. if(Root.Runtime.experiments.isEnabled('captureNodeCreationStacks')){this._agent.setNodeStackTracesEnabled(true);}}
  159. runtimeModel(){return this._runtimeModel;}
  160. cssModel(){return(this.target().model(SDK.CSSModel));}
  161. overlayModel(){return(this.target().model(SDK.OverlayModel));}
  162. static cancelSearch(){for(const domModel of SDK.targetManager.models(DOMModel)){domModel._cancelSearch();}}
  163. _scheduleMutationEvent(node){if(!this.hasEventListeners(Events.DOMMutated)){return;}
  164. this._lastMutationId=(this._lastMutationId||0)+1;Promise.resolve().then(callObserve.bind(this,node,this._lastMutationId));function callObserve(node,mutationId){if(!this.hasEventListeners(Events.DOMMutated)||this._lastMutationId!==mutationId){return;}
  165. this.dispatchEventToListeners(Events.DOMMutated,node);}}
  166. requestDocument(){if(this._document){return Promise.resolve(this._document);}
  167. if(!this._pendingDocumentRequestPromise){this._pendingDocumentRequestPromise=this._requestDocument();}
  168. return this._pendingDocumentRequestPromise;}
  169. async _requestDocument(){const documentPayload=await this._agent.getDocument();delete this._pendingDocumentRequestPromise;if(documentPayload){this._setDocument(documentPayload);}
  170. if(!this._document){console.error('No document');return null;}
  171. const parentModel=this.parentModel();if(parentModel&&!this._frameOwnerNode){await parentModel.requestDocument();const response=await parentModel._agent.invoke_getFrameOwner({frameId:this.target().id()});if(!response[Protocol.Error]){this._frameOwnerNode=parentModel.nodeForId(response.nodeId);}}
  172. if(this._frameOwnerNode){const oldDocument=this._frameOwnerNode._contentDocument;this._frameOwnerNode._contentDocument=this._document;this._frameOwnerNode._children=[];if(this._document){this._document.parentNode=this._frameOwnerNode;this.dispatchEventToListeners(Events.NodeInserted,this._document);}else if(oldDocument){this.dispatchEventToListeners(Events.NodeRemoved,{node:oldDocument,parent:this._frameOwnerNode});}}
  173. return this._document;}
  174. existingDocument(){return this._document;}
  175. async pushNodeToFrontend(objectId){await this.requestDocument();const nodeId=await this._agent.requestNode(objectId);return nodeId?this.nodeForId(nodeId):null;}
  176. pushNodeByPathToFrontend(path){return this.requestDocument().then(()=>this._agent.pushNodeByPathToFrontend(path));}
  177. async pushNodesByBackendIdsToFrontend(backendNodeIds){await this.requestDocument();const backendNodeIdsArray=backendNodeIds.valuesArray();const nodeIds=await this._agent.pushNodesByBackendIdsToFrontend(backendNodeIdsArray);if(!nodeIds){return null;}
  178. const map=new Map();for(let i=0;i<nodeIds.length;++i){if(nodeIds[i]){map.set(backendNodeIdsArray[i],this.nodeForId(nodeIds[i]));}}
  179. return map;}
  180. _wrapClientCallback(callback){function wrapper(error,result){callback(error?null:result||null);}
  181. return wrapper;}
  182. _attributeModified(nodeId,name,value){const node=this._idToDOMNode[nodeId];if(!node){return;}
  183. node._setAttribute(name,value);this.dispatchEventToListeners(Events.AttrModified,{node:node,name:name});this._scheduleMutationEvent(node);}
  184. _attributeRemoved(nodeId,name){const node=this._idToDOMNode[nodeId];if(!node){return;}
  185. node._removeAttribute(name);this.dispatchEventToListeners(Events.AttrRemoved,{node:node,name:name});this._scheduleMutationEvent(node);}
  186. _inlineStyleInvalidated(nodeIds){this._attributeLoadNodeIds.addAll(nodeIds);if(!this._loadNodeAttributesTimeout){this._loadNodeAttributesTimeout=setTimeout(this._loadNodeAttributes.bind(this),20);}}
  187. _loadNodeAttributes(){delete this._loadNodeAttributesTimeout;for(const nodeId of this._attributeLoadNodeIds){this._agent.getAttributes(nodeId).then(attributes=>{if(!attributes){return;}
  188. const node=this._idToDOMNode[nodeId];if(!node){return;}
  189. if(node._setAttributesPayload(attributes)){this.dispatchEventToListeners(Events.AttrModified,{node:node,name:'style'});this._scheduleMutationEvent(node);}});}
  190. this._attributeLoadNodeIds.clear();}
  191. _characterDataModified(nodeId,newValue){const node=this._idToDOMNode[nodeId];node._nodeValue=newValue;this.dispatchEventToListeners(Events.CharacterDataModified,node);this._scheduleMutationEvent(node);}
  192. nodeForId(nodeId){return this._idToDOMNode[nodeId]||null;}
  193. _documentUpdated(){const documentWasRequested=this._document||this._pendingDocumentRequestPromise;this._setDocument(null);if(this.parentModel()&&documentWasRequested){this.requestDocument();}}
  194. _setDocument(payload){this._idToDOMNode={};if(payload&&'nodeId'in payload){this._document=new DOMDocument(this,payload);}else{this._document=null;}
  195. SDK.domModelUndoStack._dispose(this);if(!this.parentModel()){this.dispatchEventToListeners(Events.DocumentUpdated,this);}}
  196. _setDetachedRoot(payload){if(payload.nodeName==='#document'){new DOMDocument(this,payload);}else{SDK.DOMNode.create(this,null,false,payload);}}
  197. _setChildNodes(parentId,payloads){if(!parentId&&payloads.length){this._setDetachedRoot(payloads[0]);return;}
  198. const parent=this._idToDOMNode[parentId];parent._setChildrenPayload(payloads);}
  199. _childNodeCountUpdated(nodeId,newValue){const node=this._idToDOMNode[nodeId];node._childNodeCount=newValue;this.dispatchEventToListeners(Events.ChildNodeCountUpdated,node);this._scheduleMutationEvent(node);}
  200. _childNodeInserted(parentId,prevId,payload){const parent=this._idToDOMNode[parentId];const prev=this._idToDOMNode[prevId];const node=parent._insertChild(prev,payload);this._idToDOMNode[node.id]=node;this.dispatchEventToListeners(Events.NodeInserted,node);this._scheduleMutationEvent(node);}
  201. _childNodeRemoved(parentId,nodeId){const parent=this._idToDOMNode[parentId];const node=this._idToDOMNode[nodeId];parent._removeChild(node);this._unbind(node);this.dispatchEventToListeners(Events.NodeRemoved,{node:node,parent:parent});this._scheduleMutationEvent(node);}
  202. _shadowRootPushed(hostId,root){const host=this._idToDOMNode[hostId];if(!host){return;}
  203. const node=SDK.DOMNode.create(this,host.ownerDocument,true,root);node.parentNode=host;this._idToDOMNode[node.id]=node;host._shadowRoots.unshift(node);this.dispatchEventToListeners(Events.NodeInserted,node);this._scheduleMutationEvent(node);}
  204. _shadowRootPopped(hostId,rootId){const host=this._idToDOMNode[hostId];if(!host){return;}
  205. const root=this._idToDOMNode[rootId];if(!root){return;}
  206. host._removeChild(root);this._unbind(root);this.dispatchEventToListeners(Events.NodeRemoved,{node:root,parent:host});this._scheduleMutationEvent(root);}
  207. _pseudoElementAdded(parentId,pseudoElement){const parent=this._idToDOMNode[parentId];if(!parent){return;}
  208. const node=SDK.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(Events.NodeInserted,node);this._scheduleMutationEvent(node);}
  209. _pseudoElementRemoved(parentId,pseudoElementId){const parent=this._idToDOMNode[parentId];if(!parent){return;}
  210. const pseudoElement=this._idToDOMNode[pseudoElementId];if(!pseudoElement){return;}
  211. parent._removeChild(pseudoElement);this._unbind(pseudoElement);this.dispatchEventToListeners(Events.NodeRemoved,{node:pseudoElement,parent:parent});this._scheduleMutationEvent(pseudoElement);}
  212. _distributedNodesUpdated(insertionPointId,distributedNodes){const insertionPoint=this._idToDOMNode[insertionPointId];if(!insertionPoint){return;}
  213. insertionPoint._setDistributedNodePayloads(distributedNodes);this.dispatchEventToListeners(Events.DistributedNodesChanged,insertionPoint);this._scheduleMutationEvent(insertionPoint);}
  214. _unbind(node){delete this._idToDOMNode[node.id];for(let i=0;node._children&&i<node._children.length;++i){this._unbind(node._children[i]);}
  215. for(let i=0;i<node._shadowRoots.length;++i){this._unbind(node._shadowRoots[i]);}
  216. const pseudoElements=node.pseudoElements();for(const value of pseudoElements.values()){this._unbind(value);}
  217. if(node._templateContent){this._unbind(node._templateContent);}}
  218. async performSearch(query,includeUserAgentShadowDOM){const response=await this._agent.invoke_performSearch({query,includeUserAgentShadowDOM});if(!response[Protocol.Error]){this._searchId=response.searchId;}
  219. return response[Protocol.Error]?0:response.resultCount;}
  220. async searchResult(index){if(!this._searchId){return null;}
  221. const nodeIds=await this._agent.getSearchResults(this._searchId,index,index+1);return nodeIds&&nodeIds.length===1?this.nodeForId(nodeIds[0]):null;}
  222. _cancelSearch(){if(!this._searchId){return;}
  223. this._agent.discardSearchResults(this._searchId);delete this._searchId;}
  224. classNamesPromise(nodeId){return this._agent.collectClassNamesFromSubtree(nodeId).then(classNames=>classNames||[]);}
  225. querySelector(nodeId,selectors){return this._agent.querySelector(nodeId,selectors);}
  226. querySelectorAll(nodeId,selectors){return this._agent.querySelectorAll(nodeId,selectors);}
  227. markUndoableState(minorChange){SDK.domModelUndoStack._markUndoableState(this,minorChange||false);}
  228. async nodeForLocation(x,y,includeUserAgentShadowDOM){const response=await this._agent.invoke_getNodeForLocation({x,y,includeUserAgentShadowDOM});if(response[Protocol.Error]||!response.nodeId){return null;}
  229. return this.nodeForId(response.nodeId);}
  230. pushObjectAsNodeToFrontend(object){return object.isNode()?this.pushNodeToFrontend((object.objectId)):Promise.resolve(null);}
  231. suspendModel(){return this._agent.disable().then(()=>this._setDocument(null));}
  232. resumeModel(){return this._agent.enable();}
  233. dispose(){SDK.domModelUndoStack._dispose(this);}
  234. parentModel(){const parentTarget=this.target().parentTarget();return parentTarget?parentTarget.model(DOMModel):null;}}
  235. export const Events={AttrModified:Symbol('AttrModified'),AttrRemoved:Symbol('AttrRemoved'),CharacterDataModified:Symbol('CharacterDataModified'),DOMMutated:Symbol('DOMMutated'),NodeInserted:Symbol('NodeInserted'),NodeRemoved:Symbol('NodeRemoved'),DocumentUpdated:Symbol('DocumentUpdated'),ChildNodeCountUpdated:Symbol('ChildNodeCountUpdated'),DistributedNodesChanged:Symbol('DistributedNodesChanged'),MarkersChanged:Symbol('MarkersChanged')};class DOMDispatcher{constructor(domModel){this._domModel=domModel;}
  236. documentUpdated(){this._domModel._documentUpdated();}
  237. attributeModified(nodeId,name,value){this._domModel._attributeModified(nodeId,name,value);}
  238. attributeRemoved(nodeId,name){this._domModel._attributeRemoved(nodeId,name);}
  239. inlineStyleInvalidated(nodeIds){this._domModel._inlineStyleInvalidated(nodeIds);}
  240. characterDataModified(nodeId,characterData){this._domModel._characterDataModified(nodeId,characterData);}
  241. setChildNodes(parentId,payloads){this._domModel._setChildNodes(parentId,payloads);}
  242. childNodeCountUpdated(nodeId,childNodeCount){this._domModel._childNodeCountUpdated(nodeId,childNodeCount);}
  243. childNodeInserted(parentNodeId,previousNodeId,payload){this._domModel._childNodeInserted(parentNodeId,previousNodeId,payload);}
  244. childNodeRemoved(parentNodeId,nodeId){this._domModel._childNodeRemoved(parentNodeId,nodeId);}
  245. shadowRootPushed(hostId,root){this._domModel._shadowRootPushed(hostId,root);}
  246. shadowRootPopped(hostId,rootId){this._domModel._shadowRootPopped(hostId,rootId);}
  247. pseudoElementAdded(parentId,pseudoElement){this._domModel._pseudoElementAdded(parentId,pseudoElement);}
  248. pseudoElementRemoved(parentId,pseudoElementId){this._domModel._pseudoElementRemoved(parentId,pseudoElementId);}
  249. distributedNodesUpdated(insertionPointId,distributedNodes){this._domModel._distributedNodesUpdated(insertionPointId,distributedNodes);}}
  250. class DOMModelUndoStack{constructor(){this._stack=[];this._index=0;this._lastModelWithMinorChange=null;}
  251. _markUndoableState(model,minorChange){if(this._lastModelWithMinorChange&&model!==this._lastModelWithMinorChange){this._lastModelWithMinorChange.markUndoableState();this._lastModelWithMinorChange=null;}
  252. if(minorChange&&this._lastModelWithMinorChange===model){return;}
  253. this._stack=this._stack.slice(0,this._index);this._stack.push(model);this._index=this._stack.length;if(minorChange){this._lastModelWithMinorChange=model;}else{model._agent.markUndoableState();this._lastModelWithMinorChange=null;}}
  254. undo(){if(this._index===0){return Promise.resolve();}
  255. --this._index;this._lastModelWithMinorChange=null;return this._stack[this._index]._agent.undo();}
  256. redo(){if(this._index>=this._stack.length){return Promise.resolve();}
  257. ++this._index;this._lastModelWithMinorChange=null;return this._stack[this._index-1]._agent.redo();}
  258. _dispose(model){let shift=0;for(let i=0;i<this._index;++i){if(this._stack[i]===model){++shift;}}
  259. this._stack.remove(model);this._index-=shift;if(this._lastModelWithMinorChange===model){this._lastModelWithMinorChange=null;}}}
  260. self.SDK=self.SDK||{};SDK=SDK||{};SDK.DOMModel=DOMModel;SDK.DOMModel.Events=Events;SDK.DeferredDOMNode=DeferredDOMNode;SDK.DOMNodeShortcut=DOMNodeShortcut;SDK.DOMDocument=DOMDocument;SDK.DOMNode=DOMNode;SDK.domModelUndoStack=new DOMModelUndoStack();SDK.DOMNode.Attribute;SDK.SDKModel.register(DOMModel,SDK.Target.Capability.DOM,true);