Index: third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js |
diff --git a/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js b/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js |
index bd7efffe2ffc5c872ec0f4ba5927c3e06d0b0319..2a29ee567f3ee0fb24c2ad7ef786a2529660bc25 100644 |
--- a/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js |
+++ b/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js |
@@ -23,156 +23,371 @@ |
* (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 {TreeOutlineInShadow} |
- * @param {!WebInspector.RemoteObject} object |
- * @param {?string|!Element=} title |
- * @param {!WebInspector.Linkifier=} linkifier |
- * @param {?string=} emptyPlaceholder |
- * @param {boolean=} ignoreHasOwnProperty |
- * @param {!Array.<!WebInspector.RemoteObjectProperty>=} extraProperties |
+ * @unrestricted |
*/ |
-WebInspector.ObjectPropertiesSection = function(object, title, linkifier, emptyPlaceholder, ignoreHasOwnProperty, extraProperties) |
-{ |
- TreeOutlineInShadow.call(this); |
+WebInspector.ObjectPropertiesSection = class extends TreeOutlineInShadow { |
+ /** |
+ * @param {!WebInspector.RemoteObject} object |
+ * @param {?string|!Element=} title |
+ * @param {!WebInspector.Linkifier=} linkifier |
+ * @param {?string=} emptyPlaceholder |
+ * @param {boolean=} ignoreHasOwnProperty |
+ * @param {!Array.<!WebInspector.RemoteObjectProperty>=} extraProperties |
+ */ |
+ constructor(object, title, linkifier, emptyPlaceholder, ignoreHasOwnProperty, extraProperties) { |
+ super(); |
this._object = object; |
this._editable = true; |
this.hideOverflow(); |
this.setFocusable(false); |
- this._objectTreeElement = new WebInspector.ObjectPropertiesSection.RootElement(object, linkifier, emptyPlaceholder, ignoreHasOwnProperty, extraProperties); |
+ this._objectTreeElement = new WebInspector.ObjectPropertiesSection.RootElement( |
+ object, linkifier, emptyPlaceholder, ignoreHasOwnProperty, extraProperties); |
this.appendChild(this._objectTreeElement); |
- if (typeof title === "string" || !title) { |
- this.titleElement = this.element.createChild("span"); |
- this.titleElement.textContent = title || ""; |
+ if (typeof title === 'string' || !title) { |
+ this.titleElement = this.element.createChild('span'); |
+ this.titleElement.textContent = title || ''; |
} else { |
- this.titleElement = title; |
- this.element.appendChild(title); |
+ this.titleElement = title; |
+ this.element.appendChild(title); |
} |
if (object.description && WebInspector.ObjectPropertiesSection._needsAlternateTitle(object)) { |
- this.expandedTitleElement = createElement("span"); |
- this.expandedTitleElement.createTextChild(object.description); |
+ this.expandedTitleElement = createElement('span'); |
+ this.expandedTitleElement.createTextChild(object.description); |
- var note = this.expandedTitleElement.createChild("span", "object-state-note"); |
- note.classList.add("info-note"); |
- note.title = WebInspector.UIString("Value below was evaluated just now."); |
+ var note = this.expandedTitleElement.createChild('span', 'object-state-note'); |
+ note.classList.add('info-note'); |
+ note.title = WebInspector.UIString('Value below was evaluated just now.'); |
} |
this.element._section = this; |
- this.registerRequiredCSS("components/objectValue.css"); |
- this.registerRequiredCSS("components/objectPropertiesSection.css"); |
- this.rootElement().childrenListElement.classList.add("source-code", "object-properties-section"); |
-}; |
- |
-/** @const */ |
-WebInspector.ObjectPropertiesSection._arrayLoadThreshold = 100; |
- |
-/** |
- * @param {!WebInspector.RemoteObject} object |
- * @param {!WebInspector.Linkifier=} linkifier |
- * @param {boolean=} skipProto |
- * @return {!Element} |
- */ |
-WebInspector.ObjectPropertiesSection.defaultObjectPresentation = function(object, linkifier, skipProto) |
-{ |
- var componentRoot = createElementWithClass("span", "source-code"); |
- var shadowRoot = WebInspector.createShadowRootWithCoreStyles(componentRoot, "components/objectValue.css"); |
+ this.registerRequiredCSS('components/objectValue.css'); |
+ this.registerRequiredCSS('components/objectPropertiesSection.css'); |
+ this.rootElement().childrenListElement.classList.add('source-code', 'object-properties-section'); |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.RemoteObject} object |
+ * @param {!WebInspector.Linkifier=} linkifier |
+ * @param {boolean=} skipProto |
+ * @return {!Element} |
+ */ |
+ static defaultObjectPresentation(object, linkifier, skipProto) { |
+ var componentRoot = createElementWithClass('span', 'source-code'); |
+ var shadowRoot = WebInspector.createShadowRootWithCoreStyles(componentRoot, 'components/objectValue.css'); |
shadowRoot.appendChild(WebInspector.ObjectPropertiesSection.createValueElement(object, false)); |
if (!object.hasChildren) |
- return componentRoot; |
+ return componentRoot; |
var objectPropertiesSection = new WebInspector.ObjectPropertiesSection(object, componentRoot, linkifier); |
objectPropertiesSection.editable = false; |
if (skipProto) |
- objectPropertiesSection.skipProto(); |
+ objectPropertiesSection.skipProto(); |
return objectPropertiesSection.element; |
-}; |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.RemoteObjectProperty} propertyA |
+ * @param {!WebInspector.RemoteObjectProperty} propertyB |
+ * @return {number} |
+ */ |
+ static CompareProperties(propertyA, propertyB) { |
+ var a = propertyA.name; |
+ var b = propertyB.name; |
+ if (a === '__proto__') |
+ return 1; |
+ if (b === '__proto__') |
+ return -1; |
+ if (propertyA.symbol && !propertyB.symbol) |
+ return 1; |
+ if (propertyB.symbol && !propertyA.symbol) |
+ return -1; |
+ return String.naturalOrderComparator(a, b); |
+ } |
+ |
+ /** |
+ * @param {?string} name |
+ * @return {!Element} |
+ */ |
+ static createNameElement(name) { |
+ var nameElement = createElementWithClass('span', 'name'); |
+ if (/^\s|\s$|^$|\n/.test(name)) |
+ nameElement.createTextChildren('"', name.replace(/\n/g, '\u21B5'), '"'); |
+ else |
+ nameElement.textContent = name; |
+ return nameElement; |
+ } |
+ |
+ /** |
+ * @param {?string=} description |
+ * @return {string} valueText |
+ */ |
+ static valueTextForFunctionDescription(description) { |
+ var text = description.replace(/^function [gs]et /, 'function '); |
+ var functionPrefixWithArguments = |
+ new RegExp(WebInspector.ObjectPropertiesSection._functionPrefixSource.source + '([^)]*)'); |
+ var matches = functionPrefixWithArguments.exec(text); |
+ if (!matches) { |
+ // process shorthand methods |
+ matches = /[^(]*(\([^)]*)/.exec(text); |
+ } |
+ var match = matches ? matches[1] : null; |
+ return match ? match.replace(/\n/g, ' ') + ')' : (text || ''); |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.RemoteObject} value |
+ * @param {boolean} wasThrown |
+ * @param {!Element=} parentElement |
+ * @param {!WebInspector.Linkifier=} linkifier |
+ * @return {!Element} |
+ */ |
+ static createValueElementWithCustomSupport(value, wasThrown, parentElement, linkifier) { |
+ if (value.customPreview()) { |
+ var result = (new WebInspector.CustomPreviewComponent(value)).element; |
+ result.classList.add('object-properties-section-custom-section'); |
+ return result; |
+ } |
+ return WebInspector.ObjectPropertiesSection.createValueElement(value, wasThrown, parentElement, linkifier); |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.RemoteObject} value |
+ * @param {boolean} wasThrown |
+ * @param {!Element=} parentElement |
+ * @param {!WebInspector.Linkifier=} linkifier |
+ * @return {!Element} |
+ */ |
+ static createValueElement(value, wasThrown, parentElement, linkifier) { |
+ var valueElement = createElementWithClass('span', 'value'); |
+ var type = value.type; |
+ var subtype = value.subtype; |
+ var description = value.description; |
+ var prefix; |
+ var valueText; |
+ var suffix; |
+ if (wasThrown) { |
+ prefix = '[Exception: '; |
+ valueText = description; |
+ suffix = ']'; |
+ } else if (type === 'string' && typeof description === 'string') { |
+ // Render \n as a nice unicode cr symbol. |
+ prefix = '"'; |
+ valueText = description.replace(/\n/g, '\u21B5'); |
+ suffix = '"'; |
+ } else if (type === 'function') { |
+ valueText = WebInspector.ObjectPropertiesSection.valueTextForFunctionDescription(description); |
+ } else if (type !== 'object' || subtype !== 'node') { |
+ valueText = description; |
+ } |
+ if (type !== 'number' || valueText.indexOf('e') === -1) { |
+ valueElement.setTextContentTruncatedIfNeeded(valueText || ''); |
+ if (prefix) |
+ valueElement.insertBefore(createTextNode(prefix), valueElement.firstChild); |
+ if (suffix) |
+ valueElement.createTextChild(suffix); |
+ } else { |
+ var numberParts = valueText.split('e'); |
+ var mantissa = valueElement.createChild('span', 'object-value-scientific-notation-mantissa'); |
+ mantissa.textContent = numberParts[0]; |
+ var exponent = valueElement.createChild('span', 'object-value-scientific-notation-exponent'); |
+ exponent.textContent = 'e' + numberParts[1]; |
+ valueElement.classList.add('object-value-scientific-notation-number'); |
+ if (parentElement) // FIXME: do it in the caller. |
+ parentElement.classList.add('hbox'); |
+ } |
+ |
+ if (wasThrown) |
+ valueElement.classList.add('error'); |
+ if (subtype || type) |
+ valueElement.classList.add('object-value-' + (subtype || type)); |
+ |
+ if (type === 'object' && subtype === 'node' && description) { |
+ WebInspector.DOMPresentationUtils.createSpansForNodeTitle(valueElement, description); |
+ valueElement.addEventListener('click', mouseClick, false); |
+ valueElement.addEventListener('mousemove', mouseMove, false); |
+ valueElement.addEventListener('mouseleave', mouseLeave, false); |
+ } else { |
+ valueElement.title = description || ''; |
+ } |
-WebInspector.ObjectPropertiesSection.prototype = { |
- skipProto: function() |
- { |
- this._skipProto = true; |
- }, |
+ if (type === 'object' && subtype === 'internal#location') { |
+ var rawLocation = value.debuggerModel().createRawLocationByScriptId( |
+ value.value.scriptId, value.value.lineNumber, value.value.columnNumber); |
+ if (rawLocation && linkifier) |
+ return linkifier.linkifyRawLocation(rawLocation, ''); |
+ valueElement.textContent = '<unknown>'; |
+ } |
+ |
+ function mouseMove() { |
+ WebInspector.DOMModel.highlightObjectAsDOMNode(value); |
+ } |
- expand: function() |
- { |
- this._objectTreeElement.expand(); |
- }, |
+ function mouseLeave() { |
+ WebInspector.DOMModel.hideDOMNodeHighlight(); |
+ } |
/** |
- * @param {boolean} value |
+ * @param {!Event} event |
*/ |
- setEditable: function(value) |
- { |
- this._editable = value; |
- }, |
+ function mouseClick(event) { |
+ WebInspector.Revealer.reveal(value); |
+ event.consume(true); |
+ } |
+ |
+ return valueElement; |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.RemoteObject} object |
+ * @return {boolean} |
+ */ |
+ static _needsAlternateTitle(object) { |
+ return object && object.hasChildren && !object.customPreview() && object.subtype !== 'node' && |
+ object.type !== 'function' && (object.type !== 'object' || object.preview); |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.RemoteObject} func |
+ * @param {!Element} element |
+ * @param {boolean} linkify |
+ * @param {boolean=} includePreview |
+ */ |
+ static formatObjectAsFunction(func, element, linkify, includePreview) { |
+ func.debuggerModel().functionDetailsPromise(func).then(didGetDetails); |
/** |
- * @return {!TreeElement} |
+ * @param {?WebInspector.DebuggerModel.FunctionDetails} response |
*/ |
- objectTreeElement: function() |
- { |
- return this._objectTreeElement; |
- }, |
- |
- enableContextMenu: function() |
- { |
- this.element.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), false); |
- }, |
- |
- _contextMenuEventFired: function(event) |
- { |
- var contextMenu = new WebInspector.ContextMenu(event); |
- contextMenu.appendApplicableItems(this._object); |
- contextMenu.show(); |
- }, |
- |
- titleLessMode: function() |
- { |
- this._objectTreeElement.listItemElement.classList.add("hidden"); |
- this._objectTreeElement.childrenListElement.classList.add("title-less-mode"); |
- this._objectTreeElement.expand(); |
- }, |
- |
- __proto__: TreeOutlineInShadow.prototype |
+ function didGetDetails(response) { |
+ if (!response) { |
+ var valueText = WebInspector.ObjectPropertiesSection.valueTextForFunctionDescription(func.description); |
+ element.createTextChild(valueText); |
+ return; |
+ } |
+ |
+ var matched = func.description.match(WebInspector.ObjectPropertiesSection._functionPrefixSource); |
+ if (matched) { |
+ var prefix = createElementWithClass('span', 'object-value-function-prefix'); |
+ prefix.textContent = matched[0]; |
+ element.appendChild(prefix); |
+ } |
+ |
+ if (linkify && response && response.location) { |
+ var anchor = createElement('span'); |
+ element.classList.add('linkified'); |
+ element.appendChild(anchor); |
+ element.addEventListener( |
+ 'click', WebInspector.Revealer.reveal.bind(WebInspector.Revealer, response.location, undefined)); |
+ element = anchor; |
+ } |
+ |
+ var text = func.description.substring(0, 200); |
+ if (includePreview) { |
+ element.createTextChild( |
+ text.replace(WebInspector.ObjectPropertiesSection._functionPrefixSource, '') + |
+ (func.description.length > 200 ? '\u2026' : '')); |
+ return; |
+ } |
+ |
+ // Now parse description and get the real params and title. |
+ self.runtime.extension(WebInspector.TokenizerFactory).instance().then(processTokens); |
+ |
+ var params = null; |
+ var functionName = response ? response.functionName : ''; |
+ |
+ /** |
+ * @param {!WebInspector.TokenizerFactory} tokenizerFactory |
+ */ |
+ function processTokens(tokenizerFactory) { |
+ var tokenize = tokenizerFactory.createTokenizer('text/javascript'); |
+ tokenize(text, processToken); |
+ element.createTextChild((functionName || 'anonymous') + '(' + (params || []).join(', ') + ')'); |
+ } |
+ |
+ var doneProcessing = false; |
+ |
+ /** |
+ * @param {string} token |
+ * @param {?string} tokenType |
+ * @param {number} column |
+ * @param {number} newColumn |
+ */ |
+ function processToken(token, tokenType, column, newColumn) { |
+ if (!params && tokenType === 'js-def' && !functionName) |
+ functionName = token; |
+ doneProcessing = doneProcessing || token === ')'; |
+ if (doneProcessing) |
+ return; |
+ if (token === '(') { |
+ params = []; |
+ return; |
+ } |
+ if (params && tokenType === 'js-def') |
+ params.push(token); |
+ } |
+ } |
+ } |
+ |
+ skipProto() { |
+ this._skipProto = true; |
+ } |
+ |
+ expand() { |
+ this._objectTreeElement.expand(); |
+ } |
+ |
+ /** |
+ * @param {boolean} value |
+ */ |
+ setEditable(value) { |
+ this._editable = value; |
+ } |
+ |
+ /** |
+ * @return {!TreeElement} |
+ */ |
+ objectTreeElement() { |
+ return this._objectTreeElement; |
+ } |
+ |
+ enableContextMenu() { |
+ this.element.addEventListener('contextmenu', this._contextMenuEventFired.bind(this), false); |
+ } |
+ |
+ _contextMenuEventFired(event) { |
+ var contextMenu = new WebInspector.ContextMenu(event); |
+ contextMenu.appendApplicableItems(this._object); |
+ contextMenu.show(); |
+ } |
+ |
+ titleLessMode() { |
+ this._objectTreeElement.listItemElement.classList.add('hidden'); |
+ this._objectTreeElement.childrenListElement.classList.add('title-less-mode'); |
+ this._objectTreeElement.expand(); |
+ } |
}; |
-/** |
- * @param {!WebInspector.RemoteObjectProperty} propertyA |
- * @param {!WebInspector.RemoteObjectProperty} propertyB |
- * @return {number} |
- */ |
-WebInspector.ObjectPropertiesSection.CompareProperties = function(propertyA, propertyB) |
-{ |
- var a = propertyA.name; |
- var b = propertyB.name; |
- if (a === "__proto__") |
- return 1; |
- if (b === "__proto__") |
- return -1; |
- if (propertyA.symbol && !propertyB.symbol) |
- return 1; |
- if (propertyB.symbol && !propertyA.symbol) |
- return -1; |
- return String.naturalOrderComparator(a, b); |
-}; |
+/** @const */ |
+WebInspector.ObjectPropertiesSection._arrayLoadThreshold = 100; |
+ |
/** |
- * @constructor |
- * @extends {TreeElement} |
- * @param {!WebInspector.RemoteObject} object |
- * @param {!WebInspector.Linkifier=} linkifier |
- * @param {?string=} emptyPlaceholder |
- * @param {boolean=} ignoreHasOwnProperty |
- * @param {!Array.<!WebInspector.RemoteObjectProperty>=} extraProperties |
+ * @unrestricted |
*/ |
-WebInspector.ObjectPropertiesSection.RootElement = function(object, linkifier, emptyPlaceholder, ignoreHasOwnProperty, extraProperties) |
-{ |
- var contentElement = createElement("content"); |
- TreeElement.call(this, contentElement); |
+WebInspector.ObjectPropertiesSection.RootElement = class extends TreeElement { |
+ /** |
+ * @param {!WebInspector.RemoteObject} object |
+ * @param {!WebInspector.Linkifier=} linkifier |
+ * @param {?string=} emptyPlaceholder |
+ * @param {boolean=} ignoreHasOwnProperty |
+ * @param {!Array.<!WebInspector.RemoteObjectProperty>=} extraProperties |
+ */ |
+ constructor(object, linkifier, emptyPlaceholder, ignoreHasOwnProperty, extraProperties) { |
+ var contentElement = createElement('content'); |
+ super(contentElement); |
this._object = object; |
this._extraProperties = extraProperties || []; |
@@ -182,74 +397,72 @@ WebInspector.ObjectPropertiesSection.RootElement = function(object, linkifier, e |
this.setExpandable(true); |
this.selectable = false; |
this.toggleOnClick = true; |
- this.listItemElement.classList.add("object-properties-section-root-element"); |
+ this.listItemElement.classList.add('object-properties-section-root-element'); |
this._linkifier = linkifier; |
-}; |
- |
-WebInspector.ObjectPropertiesSection.RootElement.prototype = { |
- /** |
- * @override |
- */ |
- onexpand: function() |
- { |
- if (this.treeOutline) { |
- this.treeOutline.element.classList.add("expanded"); |
- this._showExpandedTitleElement(true); |
- } |
- }, |
- |
- /** |
- * @override |
- */ |
- oncollapse: function() |
- { |
- if (this.treeOutline) { |
- this.treeOutline.element.classList.remove("expanded"); |
- this._showExpandedTitleElement(false); |
- } |
- }, |
- |
- /** |
- * @param {boolean} value |
- */ |
- _showExpandedTitleElement: function(value) |
- { |
- if (!this.treeOutline.expandedTitleElement) |
- return; |
- if (value) |
- this.treeOutline.element.replaceChild(this.treeOutline.expandedTitleElement, this.treeOutline.titleElement); |
- else |
- this.treeOutline.element.replaceChild(this.treeOutline.titleElement, this.treeOutline.expandedTitleElement); |
- }, |
- |
- /** |
- * @override |
- * @param {!Event} e |
- * @return {boolean} |
- */ |
- ondblclick: function(e) |
- { |
- return true; |
- }, |
- |
- onpopulate: function() |
- { |
- WebInspector.ObjectPropertyTreeElement._populate(this, this._object, !!this.treeOutline._skipProto, this._linkifier, this._emptyPlaceholder, this._ignoreHasOwnProperty, this._extraProperties); |
- }, |
- |
- __proto__: TreeElement.prototype |
+ } |
+ |
+ /** |
+ * @override |
+ */ |
+ onexpand() { |
+ if (this.treeOutline) { |
+ this.treeOutline.element.classList.add('expanded'); |
+ this._showExpandedTitleElement(true); |
+ } |
+ } |
+ |
+ /** |
+ * @override |
+ */ |
+ oncollapse() { |
+ if (this.treeOutline) { |
+ this.treeOutline.element.classList.remove('expanded'); |
+ this._showExpandedTitleElement(false); |
+ } |
+ } |
+ |
+ /** |
+ * @param {boolean} value |
+ */ |
+ _showExpandedTitleElement(value) { |
+ if (!this.treeOutline.expandedTitleElement) |
+ return; |
+ if (value) |
+ this.treeOutline.element.replaceChild(this.treeOutline.expandedTitleElement, this.treeOutline.titleElement); |
+ else |
+ this.treeOutline.element.replaceChild(this.treeOutline.titleElement, this.treeOutline.expandedTitleElement); |
+ } |
+ |
+ /** |
+ * @override |
+ * @param {!Event} e |
+ * @return {boolean} |
+ */ |
+ ondblclick(e) { |
+ return true; |
+ } |
+ |
+ /** |
+ * @override |
+ */ |
+ onpopulate() { |
+ WebInspector.ObjectPropertyTreeElement._populate( |
+ this, this._object, !!this.treeOutline._skipProto, this._linkifier, this._emptyPlaceholder, |
+ this._ignoreHasOwnProperty, this._extraProperties); |
+ } |
}; |
/** |
- * @constructor |
- * @extends {TreeElement} |
- * @param {!WebInspector.RemoteObjectProperty} property |
- * @param {!WebInspector.Linkifier=} linkifier |
+ * @unrestricted |
*/ |
-WebInspector.ObjectPropertyTreeElement = function(property, linkifier) |
-{ |
+WebInspector.ObjectPropertyTreeElement = class extends TreeElement { |
+ /** |
+ * @param {!WebInspector.RemoteObjectProperty} property |
+ * @param {!WebInspector.Linkifier=} linkifier |
+ */ |
+ constructor(property, linkifier) { |
// Pass an empty title, the title gets made later in onattach. |
- TreeElement.call(this); |
+ super(); |
this.property = property; |
this.toggleOnClick = true; |
@@ -257,482 +470,480 @@ WebInspector.ObjectPropertyTreeElement = function(property, linkifier) |
/** @type {!Array.<!Object>} */ |
this._highlightChanges = []; |
this._linkifier = linkifier; |
-}; |
- |
-WebInspector.ObjectPropertyTreeElement.prototype = { |
- /** |
- * @param {!RegExp} regex |
- * @param {string=} additionalCssClassName |
- * @return {boolean} |
- */ |
- setSearchRegex: function(regex, additionalCssClassName) |
- { |
- var cssClasses = WebInspector.highlightedSearchResultClassName; |
- if (additionalCssClassName) |
- cssClasses += " " + additionalCssClassName; |
- this.revertHighlightChanges(); |
- |
- this._applySearch(regex, this.nameElement, cssClasses); |
- var valueType = this.property.value.type; |
- if (valueType !== "object") |
- this._applySearch(regex, this.valueElement, cssClasses); |
- |
- return !!this._highlightChanges.length; |
- }, |
- |
- /** |
- * @param {!RegExp} regex |
- * @param {!Element} element |
- * @param {string} cssClassName |
- */ |
- _applySearch: function(regex, element, cssClassName) |
- { |
- var ranges = []; |
- var content = element.textContent; |
- regex.lastIndex = 0; |
- var match = regex.exec(content); |
- while (match) { |
- ranges.push(new WebInspector.SourceRange(match.index, match[0].length)); |
- match = regex.exec(content); |
- } |
- if (ranges.length) |
- WebInspector.highlightRangesWithStyleClass(element, ranges, cssClassName, this._highlightChanges); |
- }, |
- |
- revertHighlightChanges: function() |
- { |
- WebInspector.revertDomChanges(this._highlightChanges); |
- this._highlightChanges = []; |
- }, |
- |
- onpopulate: function() |
- { |
- var propertyValue = /** @type {!WebInspector.RemoteObject} */ (this.property.value); |
- console.assert(propertyValue); |
- var skipProto = this.treeOutline ? this.treeOutline._skipProto : true; |
- var targetValue = this.property.name !== "__proto__" ? propertyValue : this.property.parentObject; |
- WebInspector.ObjectPropertyTreeElement._populate(this, propertyValue, skipProto, this._linkifier, undefined, undefined, undefined, targetValue); |
- }, |
- |
- /** |
- * @override |
- * @return {boolean} |
- */ |
- ondblclick: function(event) |
- { |
- var inEditableElement = event.target.isSelfOrDescendant(this.valueElement) || (this.expandedValueElement && event.target.isSelfOrDescendant(this.expandedValueElement)); |
- if (!this.property.value.customPreview() && inEditableElement && (this.property.writable || this.property.setter)) |
- this._startEditing(); |
- return false; |
- }, |
- |
- /** |
- * @override |
- */ |
- onattach: function() |
- { |
- this.update(); |
- this._updateExpandable(); |
- }, |
- |
- /** |
- * @override |
- */ |
- onexpand: function() |
- { |
- this._showExpandedValueElement(true); |
- }, |
- |
- /** |
- * @override |
- */ |
- oncollapse: function() |
- { |
- this._showExpandedValueElement(false); |
- }, |
- |
- /** |
- * @param {boolean} value |
- */ |
- _showExpandedValueElement: function(value) |
- { |
- if (!this.expandedValueElement) |
- return; |
- if (value) |
- this.listItemElement.replaceChild(this.expandedValueElement, this.valueElement); |
- else |
- this.listItemElement.replaceChild(this.valueElement, this.expandedValueElement); |
- }, |
- |
- /** |
- * @param {!WebInspector.RemoteObject} value |
- * @return {?Element} |
- */ |
- _createExpandedValueElement: function(value) |
- { |
- if (!WebInspector.ObjectPropertiesSection._needsAlternateTitle(value)) |
- return null; |
- |
- var valueElement = createElementWithClass("span", "value"); |
- valueElement.setTextContentTruncatedIfNeeded(value.description || ""); |
- valueElement.classList.add("object-value-" + (value.subtype || value.type)); |
- valueElement.title = value.description || ""; |
- return valueElement; |
- }, |
- |
- update: function() |
- { |
- this.nameElement = WebInspector.ObjectPropertiesSection.createNameElement(this.property.name); |
- if (!this.property.enumerable) |
- this.nameElement.classList.add("object-properties-section-dimmed"); |
- if (this.property.synthetic) |
- this.nameElement.classList.add("synthetic-property"); |
- |
- this._updatePropertyPath(); |
- this.nameElement.addEventListener("contextmenu", this._contextMenuFired.bind(this, this.property), false); |
- |
- var separatorElement = createElementWithClass("span", "object-properties-section-separator"); |
- separatorElement.textContent = ": "; |
- |
- if (this.property.value) { |
- this.valueElement = WebInspector.ObjectPropertiesSection.createValueElementWithCustomSupport(this.property.value, this.property.wasThrown, this.listItemElement, this._linkifier); |
- this.valueElement.addEventListener("contextmenu", this._contextMenuFired.bind(this, this.property), false); |
- } else if (this.property.getter) { |
- this.valueElement = WebInspector.ObjectPropertyTreeElement.createRemoteObjectAccessorPropertySpan(this.property.parentObject, [this.property.name], this._onInvokeGetterClick.bind(this)); |
- } else { |
- this.valueElement = createElementWithClass("span", "object-value-undefined"); |
- this.valueElement.textContent = WebInspector.UIString("<unreadable>"); |
- this.valueElement.title = WebInspector.UIString("No property getter"); |
- } |
- |
- var valueText = this.valueElement.textContent; |
- if (this.property.value && valueText && !this.property.wasThrown) |
- this.expandedValueElement = this._createExpandedValueElement(this.property.value); |
- |
- this.listItemElement.removeChildren(); |
- this.listItemElement.appendChildren(this.nameElement, separatorElement, this.valueElement); |
- }, |
- |
- _updatePropertyPath: function() |
- { |
- if (this.nameElement.title) |
- return; |
- |
- var useDotNotation = /^(_|\$|[A-Z])(_|\$|[A-Z]|\d)*$/i; |
- var isInteger = /^[1-9]\d*$/; |
- var name = this.property.name; |
- var parentPath = this.parent.nameElement ? this.parent.nameElement.title : ""; |
- if (useDotNotation.test(name)) |
- this.nameElement.title = parentPath + "." + name; |
- else if (isInteger.test(name)) |
- this.nameElement.title = parentPath + "[" + name + "]"; |
- else |
- this.nameElement.title = parentPath + "[\"" + name + "\"]"; |
- }, |
- |
- /** |
- * @param {!WebInspector.RemoteObjectProperty} property |
- * @param {!Event} event |
- */ |
- _contextMenuFired: function(property, event) |
- { |
- var contextMenu = new WebInspector.ContextMenu(event); |
- if (property.symbol) |
- contextMenu.appendApplicableItems(property.symbol); |
- if (property.value) |
- contextMenu.appendApplicableItems(property.value); |
- var copyPathHandler = InspectorFrontendHost.copyText.bind(InspectorFrontendHost, this.nameElement.title); |
- contextMenu.beforeShow(() => { contextMenu.appendItem(WebInspector.UIString.capitalize("Copy ^property ^path"), copyPathHandler); }); |
- contextMenu.show(); |
- }, |
- |
- _startEditing: function() |
- { |
- if (this._prompt || !this.treeOutline._editable || this._readOnly) |
- return; |
- |
- this._editableDiv = this.listItemElement.createChild("span"); |
- |
- var text = this.property.value.description; |
- if (this.property.value.type === "string" && typeof text === "string") |
- text = "\"" + text + "\""; |
- |
- this._editableDiv.setTextContentTruncatedIfNeeded(text, WebInspector.UIString("<string is too large to edit>")); |
- var originalContent = this._editableDiv.textContent; |
- |
- // Lie about our children to prevent expanding on double click and to collapse subproperties. |
- this.setExpandable(false); |
- this.listItemElement.classList.add("editing-sub-part"); |
- this.valueElement.classList.add("hidden"); |
- |
- this._prompt = new WebInspector.ObjectPropertyPrompt(); |
- |
- var proxyElement = this._prompt.attachAndStartEditing(this._editableDiv, this._editingCommitted.bind(this, originalContent)); |
- this.listItemElement.getComponentSelection().setBaseAndExtent(this._editableDiv, 0, this._editableDiv, 1); |
- proxyElement.addEventListener("keydown", this._promptKeyDown.bind(this, originalContent), false); |
- }, |
- |
- _editingEnded: function() |
- { |
- this._prompt.detach(); |
- delete this._prompt; |
- this._editableDiv.remove(); |
- this._updateExpandable(); |
- this.listItemElement.scrollLeft = 0; |
- this.listItemElement.classList.remove("editing-sub-part"); |
- }, |
- |
- _editingCancelled: function() |
- { |
- this.valueElement.classList.remove("hidden"); |
- this._editingEnded(); |
- }, |
- |
- /** |
- * @param {string} originalContent |
- */ |
- _editingCommitted: function(originalContent) |
- { |
- var userInput = this._prompt.text(); |
- if (userInput === originalContent) { |
- this._editingCancelled(); // nothing changed, so cancel |
- return; |
- } |
- |
- this._editingEnded(); |
- this._applyExpression(userInput); |
- }, |
- |
- /** |
- * @param {string} originalContent |
- * @param {!Event} event |
- */ |
- _promptKeyDown: function(originalContent, event) |
- { |
- if (isEnterKey(event)) { |
- event.consume(true); |
- this._editingCommitted(originalContent); |
- return; |
- } |
- if (event.key === "Escape") { |
- event.consume(); |
- this._editingCancelled(); |
- return; |
- } |
- }, |
- |
- /** |
- * @param {string} expression |
- */ |
- _applyExpression: function(expression) |
- { |
- var property = WebInspector.RemoteObject.toCallArgument(this.property.symbol || this.property.name); |
- expression = expression.trim(); |
- if (expression) |
- this.property.parentObject.setPropertyValue(property, expression, callback.bind(this)); |
- else |
- this.property.parentObject.deleteProperty(property, callback.bind(this)); |
- |
- /** |
- * @param {?Protocol.Error} error |
- * @this {WebInspector.ObjectPropertyTreeElement} |
- */ |
- function callback(error) |
- { |
- if (error) { |
- this.update(); |
- return; |
- } |
- |
- if (!expression) { |
- // The property was deleted, so remove this tree element. |
- this.parent.removeChild(this); |
- } else { |
- // Call updateSiblings since their value might be based on the value that just changed. |
- var parent = this.parent; |
- parent.invalidateChildren(); |
- parent.onpopulate(); |
- } |
- } |
- }, |
- |
- /** |
- * @param {?WebInspector.RemoteObject} result |
- * @param {boolean=} wasThrown |
- */ |
- _onInvokeGetterClick: function(result, wasThrown) |
- { |
- if (!result) |
- return; |
- this.property.value = result; |
- this.property.wasThrown = wasThrown; |
- |
- this.update(); |
- this.invalidateChildren(); |
- this._updateExpandable(); |
- }, |
- |
- _updateExpandable: function() |
- { |
- if (this.property.value) |
- this.setExpandable(!this.property.value.customPreview() && this.property.value.hasChildren && !this.property.wasThrown); |
- else |
- this.setExpandable(false); |
- }, |
- |
- __proto__: TreeElement.prototype |
-}; |
- |
-/** |
- * @param {!TreeElement} treeElement |
- * @param {!WebInspector.RemoteObject} value |
- * @param {boolean} skipProto |
- * @param {!WebInspector.Linkifier=} linkifier |
- * @param {?string=} emptyPlaceholder |
- * @param {boolean=} flattenProtoChain |
- * @param {!Array.<!WebInspector.RemoteObjectProperty>=} extraProperties |
- * @param {!WebInspector.RemoteObject=} targetValue |
- */ |
-WebInspector.ObjectPropertyTreeElement._populate = function(treeElement, value, skipProto, linkifier, emptyPlaceholder, flattenProtoChain, extraProperties, targetValue) |
-{ |
+ } |
+ |
+ /** |
+ * @param {!TreeElement} treeElement |
+ * @param {!WebInspector.RemoteObject} value |
+ * @param {boolean} skipProto |
+ * @param {!WebInspector.Linkifier=} linkifier |
+ * @param {?string=} emptyPlaceholder |
+ * @param {boolean=} flattenProtoChain |
+ * @param {!Array.<!WebInspector.RemoteObjectProperty>=} extraProperties |
+ * @param {!WebInspector.RemoteObject=} targetValue |
+ */ |
+ static _populate( |
+ treeElement, |
+ value, |
+ skipProto, |
+ linkifier, |
+ emptyPlaceholder, |
+ flattenProtoChain, |
+ extraProperties, |
+ targetValue) { |
if (value.arrayLength() > WebInspector.ObjectPropertiesSection._arrayLoadThreshold) { |
- treeElement.removeChildren(); |
- WebInspector.ArrayGroupingTreeElement._populateArray(treeElement, value, 0, value.arrayLength() - 1, linkifier); |
- return; |
+ treeElement.removeChildren(); |
+ WebInspector.ArrayGroupingTreeElement._populateArray(treeElement, value, 0, value.arrayLength() - 1, linkifier); |
+ return; |
} |
/** |
* @param {?Array.<!WebInspector.RemoteObjectProperty>} properties |
* @param {?Array.<!WebInspector.RemoteObjectProperty>} internalProperties |
*/ |
- function callback(properties, internalProperties) |
- { |
- treeElement.removeChildren(); |
- if (!properties) |
- return; |
- |
- extraProperties = extraProperties || []; |
- for (var i = 0; i < extraProperties.length; ++i) |
- properties.push(extraProperties[i]); |
- |
- WebInspector.ObjectPropertyTreeElement.populateWithProperties(treeElement, properties, internalProperties, |
- skipProto, targetValue || value, linkifier, emptyPlaceholder); |
+ function callback(properties, internalProperties) { |
+ treeElement.removeChildren(); |
+ if (!properties) |
+ return; |
+ |
+ extraProperties = extraProperties || []; |
+ for (var i = 0; i < extraProperties.length; ++i) |
+ properties.push(extraProperties[i]); |
+ |
+ WebInspector.ObjectPropertyTreeElement.populateWithProperties( |
+ treeElement, properties, internalProperties, skipProto, targetValue || value, linkifier, emptyPlaceholder); |
} |
if (flattenProtoChain) |
- value.getAllProperties(false, callback); |
+ value.getAllProperties(false, callback); |
else |
- WebInspector.RemoteObject.loadFromObjectPerProto(value, callback); |
-}; |
- |
-/** |
- * @param {!TreeElement} treeNode |
- * @param {!Array.<!WebInspector.RemoteObjectProperty>} properties |
- * @param {?Array.<!WebInspector.RemoteObjectProperty>} internalProperties |
- * @param {boolean} skipProto |
- * @param {?WebInspector.RemoteObject} value |
- * @param {!WebInspector.Linkifier=} linkifier |
- * @param {?string=} emptyPlaceholder |
- */ |
-WebInspector.ObjectPropertyTreeElement.populateWithProperties = function(treeNode, properties, internalProperties, skipProto, value, linkifier, emptyPlaceholder) { |
+ WebInspector.RemoteObject.loadFromObjectPerProto(value, callback); |
+ } |
+ |
+ /** |
+ * @param {!TreeElement} treeNode |
+ * @param {!Array.<!WebInspector.RemoteObjectProperty>} properties |
+ * @param {?Array.<!WebInspector.RemoteObjectProperty>} internalProperties |
+ * @param {boolean} skipProto |
+ * @param {?WebInspector.RemoteObject} value |
+ * @param {!WebInspector.Linkifier=} linkifier |
+ * @param {?string=} emptyPlaceholder |
+ */ |
+ static populateWithProperties( |
+ treeNode, |
+ properties, |
+ internalProperties, |
+ skipProto, |
+ value, |
+ linkifier, |
+ emptyPlaceholder) { |
properties.sort(WebInspector.ObjectPropertiesSection.CompareProperties); |
var tailProperties = []; |
var protoProperty = null; |
for (var i = 0; i < properties.length; ++i) { |
- var property = properties[i]; |
- property.parentObject = value; |
- if (property.name === "__proto__" && !property.isAccessorProperty()) { |
- protoProperty = property; |
- continue; |
- } |
- |
- if (property.isOwn && property.getter) { |
- var getterProperty = new WebInspector.RemoteObjectProperty("get " + property.name, property.getter, false); |
- getterProperty.parentObject = value; |
- tailProperties.push(getterProperty); |
- } |
- if (property.isOwn && property.setter) { |
- var setterProperty = new WebInspector.RemoteObjectProperty("set " + property.name, property.setter, false); |
- setterProperty.parentObject = value; |
- tailProperties.push(setterProperty); |
- } |
- var canShowProperty = property.getter || !property.isAccessorProperty(); |
- if (canShowProperty && property.name !== "__proto__") |
- treeNode.appendChild(new WebInspector.ObjectPropertyTreeElement(property, linkifier)); |
+ var property = properties[i]; |
+ property.parentObject = value; |
+ if (property.name === '__proto__' && !property.isAccessorProperty()) { |
+ protoProperty = property; |
+ continue; |
+ } |
+ |
+ if (property.isOwn && property.getter) { |
+ var getterProperty = new WebInspector.RemoteObjectProperty('get ' + property.name, property.getter, false); |
+ getterProperty.parentObject = value; |
+ tailProperties.push(getterProperty); |
+ } |
+ if (property.isOwn && property.setter) { |
+ var setterProperty = new WebInspector.RemoteObjectProperty('set ' + property.name, property.setter, false); |
+ setterProperty.parentObject = value; |
+ tailProperties.push(setterProperty); |
+ } |
+ var canShowProperty = property.getter || !property.isAccessorProperty(); |
+ if (canShowProperty && property.name !== '__proto__') |
+ treeNode.appendChild(new WebInspector.ObjectPropertyTreeElement(property, linkifier)); |
} |
for (var i = 0; i < tailProperties.length; ++i) |
- treeNode.appendChild(new WebInspector.ObjectPropertyTreeElement(tailProperties[i], linkifier)); |
+ treeNode.appendChild(new WebInspector.ObjectPropertyTreeElement(tailProperties[i], linkifier)); |
if (!skipProto && protoProperty) |
- treeNode.appendChild(new WebInspector.ObjectPropertyTreeElement(protoProperty, linkifier)); |
+ treeNode.appendChild(new WebInspector.ObjectPropertyTreeElement(protoProperty, linkifier)); |
if (internalProperties) { |
- for (var i = 0; i < internalProperties.length; i++) { |
- internalProperties[i].parentObject = value; |
- var treeElement = new WebInspector.ObjectPropertyTreeElement(internalProperties[i], linkifier); |
- if (internalProperties[i].name === "[[Entries]]") { |
- treeElement.setExpandable(true); |
- treeElement.expand(); |
- } |
- treeNode.appendChild(treeElement); |
+ for (var i = 0; i < internalProperties.length; i++) { |
+ internalProperties[i].parentObject = value; |
+ var treeElement = new WebInspector.ObjectPropertyTreeElement(internalProperties[i], linkifier); |
+ if (internalProperties[i].name === '[[Entries]]') { |
+ treeElement.setExpandable(true); |
+ treeElement.expand(); |
} |
+ treeNode.appendChild(treeElement); |
+ } |
} |
WebInspector.ObjectPropertyTreeElement._appendEmptyPlaceholderIfNeeded(treeNode, emptyPlaceholder); |
-}; |
+ } |
-/** |
- * @param {!TreeElement} treeNode |
- * @param {?string=} emptyPlaceholder |
- */ |
-WebInspector.ObjectPropertyTreeElement._appendEmptyPlaceholderIfNeeded = function(treeNode, emptyPlaceholder) |
-{ |
+ /** |
+ * @param {!TreeElement} treeNode |
+ * @param {?string=} emptyPlaceholder |
+ */ |
+ static _appendEmptyPlaceholderIfNeeded(treeNode, emptyPlaceholder) { |
if (treeNode.childCount()) |
- return; |
- var title = createElementWithClass("div", "gray-info-message"); |
- title.textContent = emptyPlaceholder || WebInspector.UIString("No Properties"); |
+ return; |
+ var title = createElementWithClass('div', 'gray-info-message'); |
+ title.textContent = emptyPlaceholder || WebInspector.UIString('No Properties'); |
var infoElement = new TreeElement(title); |
treeNode.appendChild(infoElement); |
-}; |
- |
-/** |
- * @param {?WebInspector.RemoteObject} object |
- * @param {!Array.<string>} propertyPath |
- * @param {function(?WebInspector.RemoteObject, boolean=)} callback |
- * @return {!Element} |
- */ |
-WebInspector.ObjectPropertyTreeElement.createRemoteObjectAccessorPropertySpan = function(object, propertyPath, callback) |
-{ |
- var rootElement = createElement("span"); |
- var element = rootElement.createChild("span"); |
- element.textContent = WebInspector.UIString("(...)"); |
+ } |
+ |
+ /** |
+ * @param {?WebInspector.RemoteObject} object |
+ * @param {!Array.<string>} propertyPath |
+ * @param {function(?WebInspector.RemoteObject, boolean=)} callback |
+ * @return {!Element} |
+ */ |
+ static createRemoteObjectAccessorPropertySpan(object, propertyPath, callback) { |
+ var rootElement = createElement('span'); |
+ var element = rootElement.createChild('span'); |
+ element.textContent = WebInspector.UIString('(...)'); |
if (!object) |
- return rootElement; |
- element.classList.add("object-value-calculate-value-button"); |
- element.title = WebInspector.UIString("Invoke property getter"); |
- element.addEventListener("click", onInvokeGetterClick, false); |
- |
- function onInvokeGetterClick(event) |
- { |
- event.consume(); |
- object.getProperty(propertyPath, callback); |
+ return rootElement; |
+ element.classList.add('object-value-calculate-value-button'); |
+ element.title = WebInspector.UIString('Invoke property getter'); |
+ element.addEventListener('click', onInvokeGetterClick, false); |
+ |
+ function onInvokeGetterClick(event) { |
+ event.consume(); |
+ object.getProperty(propertyPath, callback); |
} |
return rootElement; |
+ } |
+ |
+ /** |
+ * @param {!RegExp} regex |
+ * @param {string=} additionalCssClassName |
+ * @return {boolean} |
+ */ |
+ setSearchRegex(regex, additionalCssClassName) { |
+ var cssClasses = WebInspector.highlightedSearchResultClassName; |
+ if (additionalCssClassName) |
+ cssClasses += ' ' + additionalCssClassName; |
+ this.revertHighlightChanges(); |
+ |
+ this._applySearch(regex, this.nameElement, cssClasses); |
+ var valueType = this.property.value.type; |
+ if (valueType !== 'object') |
+ this._applySearch(regex, this.valueElement, cssClasses); |
+ |
+ return !!this._highlightChanges.length; |
+ } |
+ |
+ /** |
+ * @param {!RegExp} regex |
+ * @param {!Element} element |
+ * @param {string} cssClassName |
+ */ |
+ _applySearch(regex, element, cssClassName) { |
+ var ranges = []; |
+ var content = element.textContent; |
+ regex.lastIndex = 0; |
+ var match = regex.exec(content); |
+ while (match) { |
+ ranges.push(new WebInspector.SourceRange(match.index, match[0].length)); |
+ match = regex.exec(content); |
+ } |
+ if (ranges.length) |
+ WebInspector.highlightRangesWithStyleClass(element, ranges, cssClassName, this._highlightChanges); |
+ } |
+ |
+ revertHighlightChanges() { |
+ WebInspector.revertDomChanges(this._highlightChanges); |
+ this._highlightChanges = []; |
+ } |
+ |
+ /** |
+ * @override |
+ */ |
+ onpopulate() { |
+ var propertyValue = /** @type {!WebInspector.RemoteObject} */ (this.property.value); |
+ console.assert(propertyValue); |
+ var skipProto = this.treeOutline ? this.treeOutline._skipProto : true; |
+ var targetValue = this.property.name !== '__proto__' ? propertyValue : this.property.parentObject; |
+ WebInspector.ObjectPropertyTreeElement._populate( |
+ this, propertyValue, skipProto, this._linkifier, undefined, undefined, undefined, targetValue); |
+ } |
+ |
+ /** |
+ * @override |
+ * @return {boolean} |
+ */ |
+ ondblclick(event) { |
+ var inEditableElement = event.target.isSelfOrDescendant(this.valueElement) || |
+ (this.expandedValueElement && event.target.isSelfOrDescendant(this.expandedValueElement)); |
+ if (!this.property.value.customPreview() && inEditableElement && (this.property.writable || this.property.setter)) |
+ this._startEditing(); |
+ return false; |
+ } |
+ |
+ /** |
+ * @override |
+ */ |
+ onattach() { |
+ this.update(); |
+ this._updateExpandable(); |
+ } |
+ |
+ /** |
+ * @override |
+ */ |
+ onexpand() { |
+ this._showExpandedValueElement(true); |
+ } |
+ |
+ /** |
+ * @override |
+ */ |
+ oncollapse() { |
+ this._showExpandedValueElement(false); |
+ } |
+ |
+ /** |
+ * @param {boolean} value |
+ */ |
+ _showExpandedValueElement(value) { |
+ if (!this.expandedValueElement) |
+ return; |
+ if (value) |
+ this.listItemElement.replaceChild(this.expandedValueElement, this.valueElement); |
+ else |
+ this.listItemElement.replaceChild(this.valueElement, this.expandedValueElement); |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.RemoteObject} value |
+ * @return {?Element} |
+ */ |
+ _createExpandedValueElement(value) { |
+ if (!WebInspector.ObjectPropertiesSection._needsAlternateTitle(value)) |
+ return null; |
+ |
+ var valueElement = createElementWithClass('span', 'value'); |
+ valueElement.setTextContentTruncatedIfNeeded(value.description || ''); |
+ valueElement.classList.add('object-value-' + (value.subtype || value.type)); |
+ valueElement.title = value.description || ''; |
+ return valueElement; |
+ } |
+ |
+ update() { |
+ this.nameElement = WebInspector.ObjectPropertiesSection.createNameElement(this.property.name); |
+ if (!this.property.enumerable) |
+ this.nameElement.classList.add('object-properties-section-dimmed'); |
+ if (this.property.synthetic) |
+ this.nameElement.classList.add('synthetic-property'); |
+ |
+ this._updatePropertyPath(); |
+ this.nameElement.addEventListener('contextmenu', this._contextMenuFired.bind(this, this.property), false); |
+ |
+ var separatorElement = createElementWithClass('span', 'object-properties-section-separator'); |
+ separatorElement.textContent = ': '; |
+ |
+ if (this.property.value) { |
+ this.valueElement = WebInspector.ObjectPropertiesSection.createValueElementWithCustomSupport( |
+ this.property.value, this.property.wasThrown, this.listItemElement, this._linkifier); |
+ this.valueElement.addEventListener('contextmenu', this._contextMenuFired.bind(this, this.property), false); |
+ } else if (this.property.getter) { |
+ this.valueElement = WebInspector.ObjectPropertyTreeElement.createRemoteObjectAccessorPropertySpan( |
+ this.property.parentObject, [this.property.name], this._onInvokeGetterClick.bind(this)); |
+ } else { |
+ this.valueElement = createElementWithClass('span', 'object-value-undefined'); |
+ this.valueElement.textContent = WebInspector.UIString('<unreadable>'); |
+ this.valueElement.title = WebInspector.UIString('No property getter'); |
+ } |
+ |
+ var valueText = this.valueElement.textContent; |
+ if (this.property.value && valueText && !this.property.wasThrown) |
+ this.expandedValueElement = this._createExpandedValueElement(this.property.value); |
+ |
+ this.listItemElement.removeChildren(); |
+ this.listItemElement.appendChildren(this.nameElement, separatorElement, this.valueElement); |
+ } |
+ |
+ _updatePropertyPath() { |
+ if (this.nameElement.title) |
+ return; |
+ |
+ var useDotNotation = /^(_|\$|[A-Z])(_|\$|[A-Z]|\d)*$/i; |
+ var isInteger = /^[1-9]\d*$/; |
+ var name = this.property.name; |
+ var parentPath = this.parent.nameElement ? this.parent.nameElement.title : ''; |
+ if (useDotNotation.test(name)) |
+ this.nameElement.title = parentPath + '.' + name; |
+ else if (isInteger.test(name)) |
+ this.nameElement.title = parentPath + '[' + name + ']'; |
+ else |
+ this.nameElement.title = parentPath + '["' + name + '"]'; |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.RemoteObjectProperty} property |
+ * @param {!Event} event |
+ */ |
+ _contextMenuFired(property, event) { |
+ var contextMenu = new WebInspector.ContextMenu(event); |
+ if (property.symbol) |
+ contextMenu.appendApplicableItems(property.symbol); |
+ if (property.value) |
+ contextMenu.appendApplicableItems(property.value); |
+ var copyPathHandler = InspectorFrontendHost.copyText.bind(InspectorFrontendHost, this.nameElement.title); |
+ contextMenu.beforeShow(() => { |
+ contextMenu.appendItem(WebInspector.UIString.capitalize('Copy ^property ^path'), copyPathHandler); |
+ }); |
+ contextMenu.show(); |
+ } |
+ |
+ _startEditing() { |
+ if (this._prompt || !this.treeOutline._editable || this._readOnly) |
+ return; |
+ |
+ this._editableDiv = this.listItemElement.createChild('span'); |
+ |
+ var text = this.property.value.description; |
+ if (this.property.value.type === 'string' && typeof text === 'string') |
+ text = '"' + text + '"'; |
+ |
+ this._editableDiv.setTextContentTruncatedIfNeeded(text, WebInspector.UIString('<string is too large to edit>')); |
+ var originalContent = this._editableDiv.textContent; |
+ |
+ // Lie about our children to prevent expanding on double click and to collapse subproperties. |
+ this.setExpandable(false); |
+ this.listItemElement.classList.add('editing-sub-part'); |
+ this.valueElement.classList.add('hidden'); |
+ |
+ this._prompt = new WebInspector.ObjectPropertyPrompt(); |
+ |
+ var proxyElement = |
+ this._prompt.attachAndStartEditing(this._editableDiv, this._editingCommitted.bind(this, originalContent)); |
+ this.listItemElement.getComponentSelection().setBaseAndExtent(this._editableDiv, 0, this._editableDiv, 1); |
+ proxyElement.addEventListener('keydown', this._promptKeyDown.bind(this, originalContent), false); |
+ } |
+ |
+ _editingEnded() { |
+ this._prompt.detach(); |
+ delete this._prompt; |
+ this._editableDiv.remove(); |
+ this._updateExpandable(); |
+ this.listItemElement.scrollLeft = 0; |
+ this.listItemElement.classList.remove('editing-sub-part'); |
+ } |
+ |
+ _editingCancelled() { |
+ this.valueElement.classList.remove('hidden'); |
+ this._editingEnded(); |
+ } |
+ |
+ /** |
+ * @param {string} originalContent |
+ */ |
+ _editingCommitted(originalContent) { |
+ var userInput = this._prompt.text(); |
+ if (userInput === originalContent) { |
+ this._editingCancelled(); // nothing changed, so cancel |
+ return; |
+ } |
+ |
+ this._editingEnded(); |
+ this._applyExpression(userInput); |
+ } |
+ |
+ /** |
+ * @param {string} originalContent |
+ * @param {!Event} event |
+ */ |
+ _promptKeyDown(originalContent, event) { |
+ if (isEnterKey(event)) { |
+ event.consume(true); |
+ this._editingCommitted(originalContent); |
+ return; |
+ } |
+ if (event.key === 'Escape') { |
+ event.consume(); |
+ this._editingCancelled(); |
+ return; |
+ } |
+ } |
+ |
+ /** |
+ * @param {string} expression |
+ */ |
+ _applyExpression(expression) { |
+ var property = WebInspector.RemoteObject.toCallArgument(this.property.symbol || this.property.name); |
+ expression = expression.trim(); |
+ if (expression) |
+ this.property.parentObject.setPropertyValue(property, expression, callback.bind(this)); |
+ else |
+ this.property.parentObject.deleteProperty(property, callback.bind(this)); |
+ |
+ /** |
+ * @param {?Protocol.Error} error |
+ * @this {WebInspector.ObjectPropertyTreeElement} |
+ */ |
+ function callback(error) { |
+ if (error) { |
+ this.update(); |
+ return; |
+ } |
+ |
+ if (!expression) { |
+ // The property was deleted, so remove this tree element. |
+ this.parent.removeChild(this); |
+ } else { |
+ // Call updateSiblings since their value might be based on the value that just changed. |
+ var parent = this.parent; |
+ parent.invalidateChildren(); |
+ parent.onpopulate(); |
+ } |
+ } |
+ } |
+ |
+ /** |
+ * @param {?WebInspector.RemoteObject} result |
+ * @param {boolean=} wasThrown |
+ */ |
+ _onInvokeGetterClick(result, wasThrown) { |
+ if (!result) |
+ return; |
+ this.property.value = result; |
+ this.property.wasThrown = wasThrown; |
+ |
+ this.update(); |
+ this.invalidateChildren(); |
+ this._updateExpandable(); |
+ } |
+ |
+ _updateExpandable() { |
+ if (this.property.value) |
+ this.setExpandable( |
+ !this.property.value.customPreview() && this.property.value.hasChildren && !this.property.wasThrown); |
+ else |
+ this.setExpandable(false); |
+ } |
}; |
+ |
/** |
- * @constructor |
- * @extends {TreeElement} |
- * @param {!WebInspector.RemoteObject} object |
- * @param {number} fromIndex |
- * @param {number} toIndex |
- * @param {number} propertyCount |
- * @param {!WebInspector.Linkifier=} linkifier |
+ * @unrestricted |
*/ |
-WebInspector.ArrayGroupingTreeElement = function(object, fromIndex, toIndex, propertyCount, linkifier) |
-{ |
- TreeElement.call(this, String.sprintf("[%d \u2026 %d]", fromIndex, toIndex), true); |
+WebInspector.ArrayGroupingTreeElement = class extends TreeElement { |
+ /** |
+ * @param {!WebInspector.RemoteObject} object |
+ * @param {number} fromIndex |
+ * @param {number} toIndex |
+ * @param {number} propertyCount |
+ * @param {!WebInspector.Linkifier=} linkifier |
+ */ |
+ constructor(object, fromIndex, toIndex, propertyCount, linkifier) { |
+ super(String.sprintf('[%d \u2026 %d]', fromIndex, toIndex), true); |
this.toggleOnClick = true; |
this.selectable = false; |
this._fromIndex = fromIndex; |
@@ -741,42 +952,37 @@ WebInspector.ArrayGroupingTreeElement = function(object, fromIndex, toIndex, pro |
this._readOnly = true; |
this._propertyCount = propertyCount; |
this._linkifier = linkifier; |
-}; |
- |
-WebInspector.ArrayGroupingTreeElement._bucketThreshold = 100; |
-WebInspector.ArrayGroupingTreeElement._sparseIterationThreshold = 250000; |
-WebInspector.ArrayGroupingTreeElement._getOwnPropertyNamesThreshold = 500000; |
- |
-/** |
- * @param {!TreeElement} treeNode |
- * @param {!WebInspector.RemoteObject} object |
- * @param {number} fromIndex |
- * @param {number} toIndex |
- * @param {!WebInspector.Linkifier=} linkifier |
- */ |
-WebInspector.ArrayGroupingTreeElement._populateArray = function(treeNode, object, fromIndex, toIndex, linkifier) |
-{ |
+ } |
+ |
+ /** |
+ * @param {!TreeElement} treeNode |
+ * @param {!WebInspector.RemoteObject} object |
+ * @param {number} fromIndex |
+ * @param {number} toIndex |
+ * @param {!WebInspector.Linkifier=} linkifier |
+ */ |
+ static _populateArray(treeNode, object, fromIndex, toIndex, linkifier) { |
WebInspector.ArrayGroupingTreeElement._populateRanges(treeNode, object, fromIndex, toIndex, true, linkifier); |
-}; |
- |
-/** |
- * @param {!TreeElement} treeNode |
- * @param {!WebInspector.RemoteObject} object |
- * @param {number} fromIndex |
- * @param {number} toIndex |
- * @param {boolean} topLevel |
- * @param {!WebInspector.Linkifier=} linkifier |
- * @this {WebInspector.ArrayGroupingTreeElement} |
- */ |
-WebInspector.ArrayGroupingTreeElement._populateRanges = function(treeNode, object, fromIndex, toIndex, topLevel, linkifier) |
-{ |
- object.callFunctionJSON(packRanges, [ |
- { value: fromIndex }, |
- { value: toIndex }, |
- { value: WebInspector.ArrayGroupingTreeElement._bucketThreshold }, |
- { value: WebInspector.ArrayGroupingTreeElement._sparseIterationThreshold }, |
- { value: WebInspector.ArrayGroupingTreeElement._getOwnPropertyNamesThreshold } |
- ], callback); |
+ } |
+ |
+ /** |
+ * @param {!TreeElement} treeNode |
+ * @param {!WebInspector.RemoteObject} object |
+ * @param {number} fromIndex |
+ * @param {number} toIndex |
+ * @param {boolean} topLevel |
+ * @param {!WebInspector.Linkifier=} linkifier |
+ * @this {WebInspector.ArrayGroupingTreeElement} |
+ */ |
+ static _populateRanges(treeNode, object, fromIndex, toIndex, topLevel, linkifier) { |
+ object.callFunctionJSON( |
+ packRanges, |
+ [ |
+ {value: fromIndex}, {value: toIndex}, {value: WebInspector.ArrayGroupingTreeElement._bucketThreshold}, |
+ {value: WebInspector.ArrayGroupingTreeElement._sparseIterationThreshold}, |
+ {value: WebInspector.ArrayGroupingTreeElement._getOwnPropertyNamesThreshold} |
+ ], |
+ callback); |
/** |
* Note: must declare params as optional. |
@@ -788,108 +994,113 @@ WebInspector.ArrayGroupingTreeElement._populateRanges = function(treeNode, objec |
* @suppressReceiverCheck |
* @this {Object} |
*/ |
- function packRanges(fromIndex, toIndex, bucketThreshold, sparseIterationThreshold, getOwnPropertyNamesThreshold) |
- { |
- var ownPropertyNames = null; |
- var consecutiveRange = (toIndex - fromIndex >= sparseIterationThreshold) && ArrayBuffer.isView(this); |
- var skipGetOwnPropertyNames = consecutiveRange && (toIndex - fromIndex >= getOwnPropertyNamesThreshold); |
- |
- function* arrayIndexes(object) |
- { |
- if (toIndex - fromIndex < sparseIterationThreshold) { |
- for (var i = fromIndex; i <= toIndex; ++i) { |
- if (i in object) |
- yield i; |
- } |
- } else { |
- ownPropertyNames = ownPropertyNames || Object.getOwnPropertyNames(object); |
- for (var i = 0; i < ownPropertyNames.length; ++i) { |
- var name = ownPropertyNames[i]; |
- var index = name >>> 0; |
- if (("" + index) === name && fromIndex <= index && index <= toIndex) |
- yield index; |
- } |
- } |
- } |
+ function packRanges(fromIndex, toIndex, bucketThreshold, sparseIterationThreshold, getOwnPropertyNamesThreshold) { |
+ var ownPropertyNames = null; |
+ var consecutiveRange = (toIndex - fromIndex >= sparseIterationThreshold) && ArrayBuffer.isView(this); |
+ var skipGetOwnPropertyNames = consecutiveRange && (toIndex - fromIndex >= getOwnPropertyNamesThreshold); |
- var count = 0; |
- if (consecutiveRange) { |
- count = toIndex - fromIndex + 1; |
+ function* arrayIndexes(object) { |
+ if (toIndex - fromIndex < sparseIterationThreshold) { |
+ for (var i = fromIndex; i <= toIndex; ++i) { |
+ if (i in object) |
+ yield i; |
+ } |
} else { |
- for (var i of arrayIndexes(this)) |
- ++count; |
+ ownPropertyNames = ownPropertyNames || Object.getOwnPropertyNames(object); |
+ for (var i = 0; i < ownPropertyNames.length; ++i) { |
+ var name = ownPropertyNames[i]; |
+ var index = name >>> 0; |
+ if (('' + index) === name && fromIndex <= index && index <= toIndex) |
+ yield index; |
+ } |
} |
- |
- var bucketSize = count; |
- if (count <= bucketThreshold) |
- bucketSize = count; |
- else |
- bucketSize = Math.pow(bucketThreshold, Math.ceil(Math.log(count) / Math.log(bucketThreshold)) - 1); |
- |
- var ranges = []; |
- if (consecutiveRange) { |
- for (var i = fromIndex; i <= toIndex; i += bucketSize) { |
- var groupStart = i; |
- var groupEnd = groupStart + bucketSize - 1; |
- if (groupEnd > toIndex) |
- groupEnd = toIndex; |
- ranges.push([groupStart, groupEnd, groupEnd - groupStart + 1]); |
- } |
- } else { |
+ } |
+ |
+ var count = 0; |
+ if (consecutiveRange) { |
+ count = toIndex - fromIndex + 1; |
+ } else { |
+ for (var i of arrayIndexes(this)) |
+ ++count; |
+ } |
+ |
+ var bucketSize = count; |
+ if (count <= bucketThreshold) |
+ bucketSize = count; |
+ else |
+ bucketSize = Math.pow(bucketThreshold, Math.ceil(Math.log(count) / Math.log(bucketThreshold)) - 1); |
+ |
+ var ranges = []; |
+ if (consecutiveRange) { |
+ for (var i = fromIndex; i <= toIndex; i += bucketSize) { |
+ var groupStart = i; |
+ var groupEnd = groupStart + bucketSize - 1; |
+ if (groupEnd > toIndex) |
+ groupEnd = toIndex; |
+ ranges.push([groupStart, groupEnd, groupEnd - groupStart + 1]); |
+ } |
+ } else { |
+ count = 0; |
+ var groupStart = -1; |
+ var groupEnd = 0; |
+ for (var i of arrayIndexes(this)) { |
+ if (groupStart === -1) |
+ groupStart = i; |
+ groupEnd = i; |
+ if (++count === bucketSize) { |
+ ranges.push([groupStart, groupEnd, count]); |
count = 0; |
- var groupStart = -1; |
- var groupEnd = 0; |
- for (var i of arrayIndexes(this)) { |
- if (groupStart === -1) |
- groupStart = i; |
- groupEnd = i; |
- if (++count === bucketSize) { |
- ranges.push([groupStart, groupEnd, count]); |
- count = 0; |
- groupStart = -1; |
- } |
- } |
- if (count > 0) |
- ranges.push([groupStart, groupEnd, count]); |
+ groupStart = -1; |
+ } |
} |
+ if (count > 0) |
+ ranges.push([groupStart, groupEnd, count]); |
+ } |
- return { ranges: ranges, skipGetOwnPropertyNames: skipGetOwnPropertyNames }; |
+ return {ranges: ranges, skipGetOwnPropertyNames: skipGetOwnPropertyNames}; |
} |
- function callback(result) |
- { |
- if (!result) |
- return; |
- var ranges = /** @type {!Array.<!Array.<number>>} */ (result.ranges); |
- if (ranges.length === 1) { |
- WebInspector.ArrayGroupingTreeElement._populateAsFragment(treeNode, object, ranges[0][0], ranges[0][1], linkifier); |
- } else { |
- for (var i = 0; i < ranges.length; ++i) { |
- var fromIndex = ranges[i][0]; |
- var toIndex = ranges[i][1]; |
- var count = ranges[i][2]; |
- if (fromIndex === toIndex) |
- WebInspector.ArrayGroupingTreeElement._populateAsFragment(treeNode, object, fromIndex, toIndex, linkifier); |
- else |
- treeNode.appendChild(new WebInspector.ArrayGroupingTreeElement(object, fromIndex, toIndex, count, linkifier)); |
- } |
+ function callback(result) { |
+ if (!result) |
+ return; |
+ var ranges = /** @type {!Array.<!Array.<number>>} */ (result.ranges); |
+ if (ranges.length === 1) { |
+ WebInspector.ArrayGroupingTreeElement._populateAsFragment( |
+ treeNode, object, ranges[0][0], ranges[0][1], linkifier); |
+ } else { |
+ for (var i = 0; i < ranges.length; ++i) { |
+ var fromIndex = ranges[i][0]; |
+ var toIndex = ranges[i][1]; |
+ var count = ranges[i][2]; |
+ if (fromIndex === toIndex) |
+ WebInspector.ArrayGroupingTreeElement._populateAsFragment(treeNode, object, fromIndex, toIndex, linkifier); |
+ else |
+ treeNode.appendChild( |
+ new WebInspector.ArrayGroupingTreeElement(object, fromIndex, toIndex, count, linkifier)); |
} |
- if (topLevel) |
- WebInspector.ArrayGroupingTreeElement._populateNonIndexProperties(treeNode, object, result.skipGetOwnPropertyNames, linkifier); |
+ } |
+ if (topLevel) |
+ WebInspector.ArrayGroupingTreeElement._populateNonIndexProperties( |
+ treeNode, object, result.skipGetOwnPropertyNames, linkifier); |
} |
-}; |
- |
-/** |
- * @param {!TreeElement} treeNode |
- * @param {!WebInspector.RemoteObject} object |
- * @param {number} fromIndex |
- * @param {number} toIndex |
- * @param {!WebInspector.Linkifier=} linkifier |
- * @this {WebInspector.ArrayGroupingTreeElement} |
- */ |
-WebInspector.ArrayGroupingTreeElement._populateAsFragment = function(treeNode, object, fromIndex, toIndex, linkifier) |
-{ |
- object.callFunction(buildArrayFragment, [{value: fromIndex}, {value: toIndex}, {value: WebInspector.ArrayGroupingTreeElement._sparseIterationThreshold}], processArrayFragment.bind(this)); |
+ } |
+ |
+ /** |
+ * @param {!TreeElement} treeNode |
+ * @param {!WebInspector.RemoteObject} object |
+ * @param {number} fromIndex |
+ * @param {number} toIndex |
+ * @param {!WebInspector.Linkifier=} linkifier |
+ * @this {WebInspector.ArrayGroupingTreeElement} |
+ */ |
+ static _populateAsFragment(treeNode, object, fromIndex, toIndex, linkifier) { |
+ object.callFunction( |
+ buildArrayFragment, |
+ [ |
+ {value: fromIndex}, {value: toIndex}, |
+ {value: WebInspector.ArrayGroupingTreeElement._sparseIterationThreshold} |
+ ], |
+ processArrayFragment.bind(this)); |
/** |
* @suppressReceiverCheck |
@@ -898,24 +1109,23 @@ WebInspector.ArrayGroupingTreeElement._populateAsFragment = function(treeNode, o |
* @param {number=} toIndex // must declare optional |
* @param {number=} sparseIterationThreshold // must declare optional |
*/ |
- function buildArrayFragment(fromIndex, toIndex, sparseIterationThreshold) |
- { |
- var result = Object.create(null); |
- if (toIndex - fromIndex < sparseIterationThreshold) { |
- for (var i = fromIndex; i <= toIndex; ++i) { |
- if (i in this) |
- result[i] = this[i]; |
- } |
- } else { |
- var ownPropertyNames = Object.getOwnPropertyNames(this); |
- for (var i = 0; i < ownPropertyNames.length; ++i) { |
- var name = ownPropertyNames[i]; |
- var index = name >>> 0; |
- if (String(index) === name && fromIndex <= index && index <= toIndex) |
- result[index] = this[index]; |
- } |
+ function buildArrayFragment(fromIndex, toIndex, sparseIterationThreshold) { |
+ var result = Object.create(null); |
+ if (toIndex - fromIndex < sparseIterationThreshold) { |
+ for (var i = fromIndex; i <= toIndex; ++i) { |
+ if (i in this) |
+ result[i] = this[i]; |
} |
- return result; |
+ } else { |
+ var ownPropertyNames = Object.getOwnPropertyNames(this); |
+ for (var i = 0; i < ownPropertyNames.length; ++i) { |
+ var name = ownPropertyNames[i]; |
+ var index = name >>> 0; |
+ if (String(index) === name && fromIndex <= index && index <= toIndex) |
+ result[index] = this[index]; |
+ } |
+ } |
+ return result; |
} |
/** |
@@ -923,38 +1133,35 @@ WebInspector.ArrayGroupingTreeElement._populateAsFragment = function(treeNode, o |
* @param {boolean=} wasThrown |
* @this {WebInspector.ArrayGroupingTreeElement} |
*/ |
- function processArrayFragment(arrayFragment, wasThrown) |
- { |
- if (!arrayFragment || wasThrown) |
- return; |
- arrayFragment.getAllProperties(false, processProperties.bind(this)); |
+ function processArrayFragment(arrayFragment, wasThrown) { |
+ if (!arrayFragment || wasThrown) |
+ return; |
+ arrayFragment.getAllProperties(false, processProperties.bind(this)); |
} |
/** @this {WebInspector.ArrayGroupingTreeElement} */ |
- function processProperties(properties, internalProperties) |
- { |
- if (!properties) |
- return; |
- |
- properties.sort(WebInspector.ObjectPropertiesSection.CompareProperties); |
- for (var i = 0; i < properties.length; ++i) { |
- properties[i].parentObject = this._object; |
- var childTreeElement = new WebInspector.ObjectPropertyTreeElement(properties[i], linkifier); |
- childTreeElement._readOnly = true; |
- treeNode.appendChild(childTreeElement); |
- } |
- } |
-}; |
+ function processProperties(properties, internalProperties) { |
+ if (!properties) |
+ return; |
-/** |
- * @param {!TreeElement} treeNode |
- * @param {!WebInspector.RemoteObject} object |
- * @param {boolean} skipGetOwnPropertyNames |
- * @param {!WebInspector.Linkifier=} linkifier |
- * @this {WebInspector.ArrayGroupingTreeElement} |
- */ |
-WebInspector.ArrayGroupingTreeElement._populateNonIndexProperties = function(treeNode, object, skipGetOwnPropertyNames, linkifier) |
-{ |
+ properties.sort(WebInspector.ObjectPropertiesSection.CompareProperties); |
+ for (var i = 0; i < properties.length; ++i) { |
+ properties[i].parentObject = this._object; |
+ var childTreeElement = new WebInspector.ObjectPropertyTreeElement(properties[i], linkifier); |
+ childTreeElement._readOnly = true; |
+ treeNode.appendChild(childTreeElement); |
+ } |
+ } |
+ } |
+ |
+ /** |
+ * @param {!TreeElement} treeNode |
+ * @param {!WebInspector.RemoteObject} object |
+ * @param {boolean} skipGetOwnPropertyNames |
+ * @param {!WebInspector.Linkifier=} linkifier |
+ * @this {WebInspector.ArrayGroupingTreeElement} |
+ */ |
+ static _populateNonIndexProperties(treeNode, object, skipGetOwnPropertyNames, linkifier) { |
object.callFunction(buildObjectFragment, [{value: skipGetOwnPropertyNames}], processObjectFragment.bind(this)); |
/** |
@@ -962,22 +1169,21 @@ WebInspector.ArrayGroupingTreeElement._populateNonIndexProperties = function(tre |
* @suppressReceiverCheck |
* @this {Object} |
*/ |
- function buildObjectFragment(skipGetOwnPropertyNames) |
- { |
- var result = { __proto__: this.__proto__ }; |
- if (skipGetOwnPropertyNames) |
- return result; |
- var names = Object.getOwnPropertyNames(this); |
- for (var i = 0; i < names.length; ++i) { |
- var name = names[i]; |
- // Array index check according to the ES5-15.4. |
- if (String(name >>> 0) === name && name >>> 0 !== 0xffffffff) |
- continue; |
- var descriptor = Object.getOwnPropertyDescriptor(this, name); |
- if (descriptor) |
- Object.defineProperty(result, name, descriptor); |
- } |
+ function buildObjectFragment(skipGetOwnPropertyNames) { |
+ var result = {__proto__: this.__proto__}; |
+ if (skipGetOwnPropertyNames) |
return result; |
+ var names = Object.getOwnPropertyNames(this); |
+ for (var i = 0; i < names.length; ++i) { |
+ var name = names[i]; |
+ // Array index check according to the ES5-15.4. |
+ if (String(name >>> 0) === name && name >>> 0 !== 0xffffffff) |
+ continue; |
+ var descriptor = Object.getOwnPropertyDescriptor(this, name); |
+ if (descriptor) |
+ Object.defineProperty(result, name, descriptor); |
+ } |
+ return result; |
} |
/** |
@@ -985,11 +1191,10 @@ WebInspector.ArrayGroupingTreeElement._populateNonIndexProperties = function(tre |
* @param {boolean=} wasThrown |
* @this {WebInspector.ArrayGroupingTreeElement} |
*/ |
- function processObjectFragment(arrayFragment, wasThrown) |
- { |
- if (!arrayFragment || wasThrown) |
- return; |
- arrayFragment.getOwnProperties(processProperties.bind(this)); |
+ function processObjectFragment(arrayFragment, wasThrown) { |
+ if (!arrayFragment || wasThrown) |
+ return; |
+ arrayFragment.getOwnProperties(processProperties.bind(this)); |
} |
/** |
@@ -997,380 +1202,148 @@ WebInspector.ArrayGroupingTreeElement._populateNonIndexProperties = function(tre |
* @param {?Array.<!WebInspector.RemoteObjectProperty>=} internalProperties |
* @this {WebInspector.ArrayGroupingTreeElement} |
*/ |
- function processProperties(properties, internalProperties) |
- { |
- if (!properties) |
- return; |
- properties.sort(WebInspector.ObjectPropertiesSection.CompareProperties); |
- for (var i = 0; i < properties.length; ++i) { |
- properties[i].parentObject = this._object; |
- var childTreeElement = new WebInspector.ObjectPropertyTreeElement(properties[i], linkifier); |
- childTreeElement._readOnly = true; |
- treeNode.appendChild(childTreeElement); |
- } |
+ function processProperties(properties, internalProperties) { |
+ if (!properties) |
+ return; |
+ properties.sort(WebInspector.ObjectPropertiesSection.CompareProperties); |
+ for (var i = 0; i < properties.length; ++i) { |
+ properties[i].parentObject = this._object; |
+ var childTreeElement = new WebInspector.ObjectPropertyTreeElement(properties[i], linkifier); |
+ childTreeElement._readOnly = true; |
+ treeNode.appendChild(childTreeElement); |
+ } |
+ } |
+ } |
+ |
+ /** |
+ * @override |
+ */ |
+ onpopulate() { |
+ if (this._propertyCount >= WebInspector.ArrayGroupingTreeElement._bucketThreshold) { |
+ WebInspector.ArrayGroupingTreeElement._populateRanges( |
+ this, this._object, this._fromIndex, this._toIndex, false, this._linkifier); |
+ return; |
} |
+ WebInspector.ArrayGroupingTreeElement._populateAsFragment( |
+ this, this._object, this._fromIndex, this._toIndex, this._linkifier); |
+ } |
+ |
+ /** |
+ * @override |
+ */ |
+ onattach() { |
+ this.listItemElement.classList.add('object-properties-section-name'); |
+ } |
}; |
-WebInspector.ArrayGroupingTreeElement.prototype = { |
- onpopulate: function() |
- { |
- if (this._propertyCount >= WebInspector.ArrayGroupingTreeElement._bucketThreshold) { |
- WebInspector.ArrayGroupingTreeElement._populateRanges(this, this._object, this._fromIndex, this._toIndex, false, this._linkifier); |
- return; |
- } |
- WebInspector.ArrayGroupingTreeElement._populateAsFragment(this, this._object, this._fromIndex, this._toIndex, this._linkifier); |
- }, |
- |
- onattach: function() |
- { |
- this.listItemElement.classList.add("object-properties-section-name"); |
- }, |
+WebInspector.ArrayGroupingTreeElement._bucketThreshold = 100; |
+WebInspector.ArrayGroupingTreeElement._sparseIterationThreshold = 250000; |
+WebInspector.ArrayGroupingTreeElement._getOwnPropertyNamesThreshold = 500000; |
- __proto__: TreeElement.prototype |
-}; |
/** |
- * @constructor |
- * @extends {WebInspector.TextPrompt} |
+ * @unrestricted |
*/ |
-WebInspector.ObjectPropertyPrompt = function() |
-{ |
- WebInspector.TextPrompt.call(this); |
+WebInspector.ObjectPropertyPrompt = class extends WebInspector.TextPrompt { |
+ constructor() { |
+ super(); |
this.initialize(WebInspector.ExecutionContextSelector.completionsForTextPromptInCurrentContext); |
this.setSuggestBoxEnabled(true); |
+ } |
}; |
-WebInspector.ObjectPropertyPrompt.prototype = { |
- __proto__: WebInspector.TextPrompt.prototype |
-}; |
- |
-/** |
- * @param {?string} name |
- * @return {!Element} |
- */ |
-WebInspector.ObjectPropertiesSection.createNameElement = function(name) |
-{ |
- var nameElement = createElementWithClass("span", "name"); |
- if (/^\s|\s$|^$|\n/.test(name)) |
- nameElement.createTextChildren("\"", name.replace(/\n/g, "\u21B5"), "\""); |
- else |
- nameElement.textContent = name; |
- return nameElement; |
-}; |
WebInspector.ObjectPropertiesSection._functionPrefixSource = /^(?:async\s)?function\*?\s/; |
-/** |
- * @param {?string=} description |
- * @return {string} valueText |
- */ |
-WebInspector.ObjectPropertiesSection.valueTextForFunctionDescription = function(description) |
-{ |
- var text = description.replace(/^function [gs]et /, "function "); |
- var functionPrefixWithArguments = new RegExp(WebInspector.ObjectPropertiesSection._functionPrefixSource.source + "([^)]*)"); |
- var matches = functionPrefixWithArguments.exec(text); |
- if (!matches) { |
- // process shorthand methods |
- matches = /[^(]*(\([^)]*)/.exec(text); |
- } |
- var match = matches ? matches[1] : null; |
- return match ? match.replace(/\n/g, " ") + ")" : (text || ""); |
-}; |
- |
-/** |
- * @param {!WebInspector.RemoteObject} value |
- * @param {boolean} wasThrown |
- * @param {!Element=} parentElement |
- * @param {!WebInspector.Linkifier=} linkifier |
- * @return {!Element} |
- */ |
-WebInspector.ObjectPropertiesSection.createValueElementWithCustomSupport = function(value, wasThrown, parentElement, linkifier) |
-{ |
- if (value.customPreview()) { |
- var result = (new WebInspector.CustomPreviewComponent(value)).element; |
- result.classList.add("object-properties-section-custom-section"); |
- return result; |
- } |
- return WebInspector.ObjectPropertiesSection.createValueElement(value, wasThrown, parentElement, linkifier); |
-}; |
/** |
- * @param {!WebInspector.RemoteObject} value |
- * @param {boolean} wasThrown |
- * @param {!Element=} parentElement |
- * @param {!WebInspector.Linkifier=} linkifier |
- * @return {!Element} |
+ * @unrestricted |
*/ |
-WebInspector.ObjectPropertiesSection.createValueElement = function(value, wasThrown, parentElement, linkifier) |
-{ |
- var valueElement = createElementWithClass("span", "value"); |
- var type = value.type; |
- var subtype = value.subtype; |
- var description = value.description; |
- var prefix; |
- var valueText; |
- var suffix; |
- if (wasThrown) { |
- prefix = "[Exception: "; |
- valueText = description; |
- suffix = "]"; |
- } else if (type === "string" && typeof description === "string") { |
- // Render \n as a nice unicode cr symbol. |
- prefix = "\""; |
- valueText = description.replace(/\n/g, "\u21B5"); |
- suffix = "\""; |
- } else if (type === "function") { |
- valueText = WebInspector.ObjectPropertiesSection.valueTextForFunctionDescription(description); |
- } else if (type !== "object" || subtype !== "node") { |
- valueText = description; |
- } |
- if (type !== "number" || valueText.indexOf("e") === -1) { |
- valueElement.setTextContentTruncatedIfNeeded(valueText || ""); |
- if (prefix) |
- valueElement.insertBefore(createTextNode(prefix), valueElement.firstChild); |
- if (suffix) |
- valueElement.createTextChild(suffix); |
- } else { |
- var numberParts = valueText.split("e"); |
- var mantissa = valueElement.createChild("span", "object-value-scientific-notation-mantissa"); |
- mantissa.textContent = numberParts[0]; |
- var exponent = valueElement.createChild("span", "object-value-scientific-notation-exponent"); |
- exponent.textContent = "e" + numberParts[1]; |
- valueElement.classList.add("object-value-scientific-notation-number"); |
- if (parentElement) // FIXME: do it in the caller. |
- parentElement.classList.add("hbox"); |
- } |
- |
- if (wasThrown) |
- valueElement.classList.add("error"); |
- if (subtype || type) |
- valueElement.classList.add("object-value-" + (subtype || type)); |
- |
- if (type === "object" && subtype === "node" && description) { |
- WebInspector.DOMPresentationUtils.createSpansForNodeTitle(valueElement, description); |
- valueElement.addEventListener("click", mouseClick, false); |
- valueElement.addEventListener("mousemove", mouseMove, false); |
- valueElement.addEventListener("mouseleave", mouseLeave, false); |
- } else { |
- valueElement.title = description || ""; |
- } |
- |
- if (type === "object" && subtype === "internal#location") { |
- var rawLocation = value.debuggerModel().createRawLocationByScriptId(value.value.scriptId, value.value.lineNumber, value.value.columnNumber); |
- if (rawLocation && linkifier) |
- return linkifier.linkifyRawLocation(rawLocation, ""); |
- valueElement.textContent = "<unknown>"; |
- } |
- |
- function mouseMove() |
- { |
- WebInspector.DOMModel.highlightObjectAsDOMNode(value); |
- } |
- |
- function mouseLeave() |
- { |
- WebInspector.DOMModel.hideDOMNodeHighlight(); |
- } |
- |
- /** |
- * @param {!Event} event |
- */ |
- function mouseClick(event) |
- { |
- WebInspector.Revealer.reveal(value); |
- event.consume(true); |
- } |
- |
- return valueElement; |
-}; |
- |
-/** |
- * @param {!WebInspector.RemoteObject} object |
- * @return {boolean} |
- */ |
-WebInspector.ObjectPropertiesSection._needsAlternateTitle = function(object) |
-{ |
- return object && object.hasChildren && !object.customPreview() && object.subtype !== "node" && object.type !== "function" && (object.type !== "object" || object.preview); |
-}; |
- |
-/** |
- * @param {!WebInspector.RemoteObject} func |
- * @param {!Element} element |
- * @param {boolean} linkify |
- * @param {boolean=} includePreview |
- */ |
-WebInspector.ObjectPropertiesSection.formatObjectAsFunction = function(func, element, linkify, includePreview) |
-{ |
- func.debuggerModel().functionDetailsPromise(func).then(didGetDetails); |
- |
- /** |
- * @param {?WebInspector.DebuggerModel.FunctionDetails} response |
- */ |
- function didGetDetails(response) |
- { |
- if (!response) { |
- var valueText = WebInspector.ObjectPropertiesSection.valueTextForFunctionDescription(func.description); |
- element.createTextChild(valueText); |
- return; |
- } |
- |
- var matched = func.description.match(WebInspector.ObjectPropertiesSection._functionPrefixSource); |
- if (matched) { |
- var prefix = createElementWithClass("span", "object-value-function-prefix"); |
- prefix.textContent = matched[0]; |
- element.appendChild(prefix); |
- } |
- |
- if (linkify && response && response.location) { |
- var anchor = createElement("span"); |
- element.classList.add("linkified"); |
- element.appendChild(anchor); |
- element.addEventListener("click", WebInspector.Revealer.reveal.bind(WebInspector.Revealer, response.location, undefined)); |
- element = anchor; |
- } |
- |
- var text = func.description.substring(0, 200); |
- if (includePreview) { |
- element.createTextChild(text.replace(WebInspector.ObjectPropertiesSection._functionPrefixSource, "") + (func.description.length > 200 ? "\u2026" : "")); |
- return; |
- } |
- |
- // Now parse description and get the real params and title. |
- self.runtime.extension(WebInspector.TokenizerFactory).instance().then(processTokens); |
- |
- var params = null; |
- var functionName = response ? response.functionName : ""; |
- |
- /** |
- * @param {!WebInspector.TokenizerFactory} tokenizerFactory |
- */ |
- function processTokens(tokenizerFactory) |
- { |
- var tokenize = tokenizerFactory.createTokenizer("text/javascript"); |
- tokenize(text, processToken); |
- element.createTextChild((functionName || "anonymous") + "(" + (params || []).join(", ") + ")"); |
- } |
- |
- var doneProcessing = false; |
- |
- /** |
- * @param {string} token |
- * @param {?string} tokenType |
- * @param {number} column |
- * @param {number} newColumn |
- */ |
- function processToken(token, tokenType, column, newColumn) |
- { |
- if (!params && tokenType === "js-def" && !functionName) |
- functionName = token; |
- doneProcessing = doneProcessing || token === ")"; |
- if (doneProcessing) |
- return; |
- if (token === "(") { |
- params = []; |
- return; |
- } |
- if (params && tokenType === "js-def") |
- params.push(token); |
- } |
- } |
-}; |
- |
-/** |
- * @constructor |
- */ |
-WebInspector.ObjectPropertiesSectionExpandController = function() |
-{ |
+WebInspector.ObjectPropertiesSectionExpandController = class { |
+ constructor() { |
/** @type {!Set.<string>} */ |
this._expandedProperties = new Set(); |
-}; |
- |
-WebInspector.ObjectPropertiesSectionExpandController._cachedPathSymbol = Symbol("cachedPath"); |
-WebInspector.ObjectPropertiesSectionExpandController._treeOutlineId = Symbol("treeOutlineId"); |
- |
-WebInspector.ObjectPropertiesSectionExpandController.prototype = { |
- /** |
- * @param {string} id |
- * @param {!WebInspector.ObjectPropertiesSection} section |
- */ |
- watchSection: function(id, section) |
- { |
- section.addEventListener(TreeOutline.Events.ElementAttached, this._elementAttached, this); |
- section.addEventListener(TreeOutline.Events.ElementExpanded, this._elementExpanded, this); |
- section.addEventListener(TreeOutline.Events.ElementCollapsed, this._elementCollapsed, this); |
- section[WebInspector.ObjectPropertiesSectionExpandController._treeOutlineId] = id; |
- |
- if (this._expandedProperties.has(id)) |
- section.expand(); |
- }, |
- |
- /** |
- * @param {string} id |
- */ |
- stopWatchSectionsWithId: function(id) |
- { |
- for (var property of this._expandedProperties) { |
- if (property.startsWith(id + ":")) |
- this._expandedProperties.delete(property); |
- } |
- }, |
- |
- /** |
- * @param {!WebInspector.Event} event |
- */ |
- _elementAttached: function(event) |
- { |
- var element = /** @type {!TreeElement} */ (event.data); |
- if (element.isExpandable() && this._expandedProperties.has(this._propertyPath(element))) |
- element.expand(); |
- }, |
- |
- /** |
- * @param {!WebInspector.Event} event |
- */ |
- _elementExpanded: function(event) |
- { |
- var element = /** @type {!TreeElement} */ (event.data); |
- this._expandedProperties.add(this._propertyPath(element)); |
- }, |
- |
- /** |
- * @param {!WebInspector.Event} event |
- */ |
- _elementCollapsed: function(event) |
- { |
- var element = /** @type {!TreeElement} */ (event.data); |
- this._expandedProperties.delete(this._propertyPath(element)); |
- }, |
- |
- /** |
- * @param {!TreeElement} treeElement |
- * @return {string} |
- */ |
- _propertyPath: function(treeElement) |
- { |
- var cachedPropertyPath = treeElement[WebInspector.ObjectPropertiesSectionExpandController._cachedPathSymbol]; |
- if (cachedPropertyPath) |
- return cachedPropertyPath; |
- |
- var current = treeElement; |
- var rootElement = treeElement.treeOutline.objectTreeElement(); |
- |
- var result; |
- |
- while (current !== rootElement) { |
- var currentName = ""; |
- if (current.property) |
- currentName = current.property.name; |
- else |
- currentName = typeof current.title === "string" ? current.title : current.title.textContent; |
- |
- result = currentName + (result ? "." + result : ""); |
- current = current.parent; |
- } |
- var treeOutlineId = treeElement.treeOutline[WebInspector.ObjectPropertiesSectionExpandController._treeOutlineId]; |
- result = treeOutlineId + (result ? ":" + result : ""); |
- treeElement[WebInspector.ObjectPropertiesSectionExpandController._cachedPathSymbol] = result; |
- return result; |
+ } |
+ |
+ /** |
+ * @param {string} id |
+ * @param {!WebInspector.ObjectPropertiesSection} section |
+ */ |
+ watchSection(id, section) { |
+ section.addEventListener(TreeOutline.Events.ElementAttached, this._elementAttached, this); |
+ section.addEventListener(TreeOutline.Events.ElementExpanded, this._elementExpanded, this); |
+ section.addEventListener(TreeOutline.Events.ElementCollapsed, this._elementCollapsed, this); |
+ section[WebInspector.ObjectPropertiesSectionExpandController._treeOutlineId] = id; |
+ |
+ if (this._expandedProperties.has(id)) |
+ section.expand(); |
+ } |
+ |
+ /** |
+ * @param {string} id |
+ */ |
+ stopWatchSectionsWithId(id) { |
+ for (var property of this._expandedProperties) { |
+ if (property.startsWith(id + ':')) |
+ this._expandedProperties.delete(property); |
} |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.Event} event |
+ */ |
+ _elementAttached(event) { |
+ var element = /** @type {!TreeElement} */ (event.data); |
+ if (element.isExpandable() && this._expandedProperties.has(this._propertyPath(element))) |
+ element.expand(); |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.Event} event |
+ */ |
+ _elementExpanded(event) { |
+ var element = /** @type {!TreeElement} */ (event.data); |
+ this._expandedProperties.add(this._propertyPath(element)); |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.Event} event |
+ */ |
+ _elementCollapsed(event) { |
+ var element = /** @type {!TreeElement} */ (event.data); |
+ this._expandedProperties.delete(this._propertyPath(element)); |
+ } |
+ |
+ /** |
+ * @param {!TreeElement} treeElement |
+ * @return {string} |
+ */ |
+ _propertyPath(treeElement) { |
+ var cachedPropertyPath = treeElement[WebInspector.ObjectPropertiesSectionExpandController._cachedPathSymbol]; |
+ if (cachedPropertyPath) |
+ return cachedPropertyPath; |
+ |
+ var current = treeElement; |
+ var rootElement = treeElement.treeOutline.objectTreeElement(); |
+ |
+ var result; |
+ |
+ while (current !== rootElement) { |
+ var currentName = ''; |
+ if (current.property) |
+ currentName = current.property.name; |
+ else |
+ currentName = typeof current.title === 'string' ? current.title : current.title.textContent; |
+ |
+ result = currentName + (result ? '.' + result : ''); |
+ current = current.parent; |
+ } |
+ var treeOutlineId = treeElement.treeOutline[WebInspector.ObjectPropertiesSectionExpandController._treeOutlineId]; |
+ result = treeOutlineId + (result ? ':' + result : ''); |
+ treeElement[WebInspector.ObjectPropertiesSectionExpandController._cachedPathSymbol] = result; |
+ return result; |
+ } |
}; |
+ |
+WebInspector.ObjectPropertiesSectionExpandController._cachedPathSymbol = Symbol('cachedPath'); |
+WebInspector.ObjectPropertiesSectionExpandController._treeOutlineId = Symbol('treeOutlineId'); |