RemoteObjectPreviewFormatter.js 7.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940
  1. export default class RemoteObjectPreviewFormatter{static _objectPropertyComparator(a,b){return sortValue(a)-sortValue(b);function sortValue(property){const internalName=_internalName;if(property.name===internalName.PromiseStatus){return 1;}else if(property.name===internalName.PromiseValue){return 2;}else if(property.name===internalName.GeneratorStatus||property.name===internalName.PrimitiveValue){return 3;}
  2. else if(property.type!=='function'&&!property.name.startsWith('#')){return 4;}
  3. return 5;}}
  4. appendObjectPreview(parentElement,preview,isEntry){const description=preview.description;const subTypesWithoutValuePreview=new Set(['null','regexp','error','internal#entry']);if(preview.type!=='object'||subTypesWithoutValuePreview.has(preview.subtype)||isEntry){parentElement.appendChild(this.renderPropertyPreview(preview.type,preview.subtype,description));return;}
  5. const isArrayOrTypedArray=preview.subtype==='array'||preview.subtype==='typedarray';if(description){let text;if(isArrayOrTypedArray){const arrayLength=SDK.RemoteObject.arrayLength(preview);const arrayLengthText=arrayLength>1?('('+arrayLength+')'):'';const arrayName=SDK.RemoteObject.arrayNameFromDescription(description);text=arrayName==='Array'?arrayLengthText:(arrayName+arrayLengthText);}else{const hideDescription=description==='Object';text=hideDescription?'':description;}
  6. if(text.length>0){parentElement.createChild('span','object-description').textContent=text+'\xA0';}}
  7. const propertiesElement=parentElement.createChild('span','object-properties-preview');propertiesElement.createTextChild(isArrayOrTypedArray?'[':'{');if(preview.entries){this._appendEntriesPreview(propertiesElement,preview);}else if(isArrayOrTypedArray){this._appendArrayPropertiesPreview(propertiesElement,preview);}else{this._appendObjectPropertiesPreview(propertiesElement,preview);}
  8. if(preview.overflow){const ellipsisText=propertiesElement.textContent.length>1?',\xA0\u2026':'\u2026';propertiesElement.createChild('span').textContent=ellipsisText;}
  9. propertiesElement.createTextChild(isArrayOrTypedArray?']':'}');}
  10. _abbreviateFullQualifiedClassName(description){const abbreviatedDescription=description.split('.');for(let i=0;i<abbreviatedDescription.length-1;++i){abbreviatedDescription[i]=abbreviatedDescription[i].trimMiddle(3);}
  11. return abbreviatedDescription.join('.');}
  12. _appendObjectPropertiesPreview(parentElement,preview){const internalName=_internalName;const properties=preview.properties.filter(p=>p.type!=='accessor').sort(RemoteObjectPreviewFormatter._objectPropertyComparator);for(let i=0;i<properties.length;++i){if(i>0){parentElement.createTextChild(', ');}
  13. const property=properties[i];const name=property.name;if(preview.subtype==='promise'&&name===internalName.PromiseStatus){parentElement.appendChild(this._renderDisplayName('<'+property.value+'>'));const nextProperty=i+1<properties.length?properties[i+1]:null;if(nextProperty&&nextProperty.name===internalName.PromiseValue){if(property.value!=='pending'){parentElement.createTextChild(': ');parentElement.appendChild(this._renderPropertyPreviewOrAccessor([nextProperty]));}
  14. i++;}}else if(preview.subtype==='generator'&&name===internalName.GeneratorStatus){parentElement.appendChild(this._renderDisplayName('<'+property.value+'>'));}else if(name===internalName.PrimitiveValue){parentElement.appendChild(this._renderPropertyPreviewOrAccessor([property]));}else{parentElement.appendChild(this._renderDisplayName(name));parentElement.createTextChild(': ');parentElement.appendChild(this._renderPropertyPreviewOrAccessor([property]));}}}
  15. _appendArrayPropertiesPreview(parentElement,preview){const arrayLength=SDK.RemoteObject.arrayLength(preview);const indexProperties=preview.properties.filter(p=>toArrayIndex(p.name)!==-1).sort(arrayEntryComparator);const otherProperties=preview.properties.filter(p=>toArrayIndex(p.name)===-1).sort(RemoteObjectPreviewFormatter._objectPropertyComparator);function arrayEntryComparator(a,b){return toArrayIndex(a.name)-toArrayIndex(b.name);}
  16. function toArrayIndex(name){const index=name>>>0;if(String(index)===name&&index<arrayLength){return index;}
  17. return-1;}
  18. const canShowGaps=!preview.overflow;let lastNonEmptyArrayIndex=-1;let elementsAdded=false;for(let i=0;i<indexProperties.length;++i){if(elementsAdded){parentElement.createTextChild(', ');}
  19. const property=indexProperties[i];const index=toArrayIndex(property.name);if(canShowGaps&&index-lastNonEmptyArrayIndex>1){appendUndefined(index);parentElement.createTextChild(', ');}
  20. if(!canShowGaps&&i!==index){parentElement.appendChild(this._renderDisplayName(property.name));parentElement.createTextChild(': ');}
  21. parentElement.appendChild(this._renderPropertyPreviewOrAccessor([property]));lastNonEmptyArrayIndex=index;elementsAdded=true;}
  22. if(canShowGaps&&arrayLength-lastNonEmptyArrayIndex>1){if(elementsAdded){parentElement.createTextChild(', ');}
  23. appendUndefined(arrayLength);}
  24. for(let i=0;i<otherProperties.length;++i){if(elementsAdded){parentElement.createTextChild(', ');}
  25. const property=otherProperties[i];parentElement.appendChild(this._renderDisplayName(property.name));parentElement.createTextChild(': ');parentElement.appendChild(this._renderPropertyPreviewOrAccessor([property]));elementsAdded=true;}
  26. function appendUndefined(index){const span=parentElement.createChild('span','object-value-undefined');const count=index-lastNonEmptyArrayIndex-1;span.textContent=count!==1?Common.UIString('empty × %d',count):Common.UIString('empty');elementsAdded=true;}}
  27. _appendEntriesPreview(parentElement,preview){for(let i=0;i<preview.entries.length;++i){if(i>0){parentElement.createTextChild(', ');}
  28. const entry=preview.entries[i];if(entry.key){this.appendObjectPreview(parentElement,entry.key,true);parentElement.createTextChild(' => ');}
  29. this.appendObjectPreview(parentElement,entry.value,true);}}
  30. _renderDisplayName(name){const result=createElementWithClass('span','name');const needsQuotes=/^\s|\s$|^$|\n/.test(name);result.textContent=needsQuotes?'"'+name.replace(/\n/g,'\u21B5')+'"':name;return result;}
  31. _renderPropertyPreviewOrAccessor(propertyPath){const property=propertyPath.peekLast();return this.renderPropertyPreview(property.type,(property.subtype),property.value);}
  32. renderPropertyPreview(type,subtype,description){const span=createElementWithClass('span','object-value-'+(subtype||type));description=description||'';if(type==='accessor'){span.textContent='(...)';span.title=Common.UIString('The property is computed with a getter');return span;}
  33. if(type==='function'){span.textContent='\u0192';return span;}
  34. if(type==='object'&&subtype==='node'&&description){createSpansForNodeTitle(span,description);return span;}
  35. if(type==='string'){span.createTextChildren('"',description.replace(/\n/g,'\u21B5'),'"');return span;}
  36. if(type==='object'&&!subtype){let preview=this._abbreviateFullQualifiedClassName(description);if(preview==='Object'){preview='{\u2026}';}
  37. span.textContent=preview;span.title=description;return span;}
  38. span.textContent=description;return span;}}
  39. const _internalName={GeneratorStatus:'[[GeneratorStatus]]',PrimitiveValue:'[[PrimitiveValue]]',PromiseStatus:'[[PromiseStatus]]',PromiseValue:'[[PromiseValue]]'};export const createSpansForNodeTitle=function(container,nodeTitle){const match=nodeTitle.match(/([^#.]+)(#[^.]+)?(\..*)?/);container.createChild('span','webkit-html-tag-name').textContent=match[1];if(match[2]){container.createChild('span','webkit-html-attribute-value').textContent=match[2];}
  40. if(match[3]){container.createChild('span','webkit-html-attribute-name').textContent=match[3];}};self.ObjectUI=self.ObjectUI||{};ObjectUI=ObjectUI||{};ObjectUI.RemoteObjectPreviewFormatter=RemoteObjectPreviewFormatter;ObjectUI.RemoteObjectPreviewFormatter.createSpansForNodeTitle=createSpansForNodeTitle;