Chromium Code Reviews| Index: Source/devtools/front_end/ConsoleMessage.js |
| diff --git a/Source/devtools/front_end/ConsoleMessage.js b/Source/devtools/front_end/ConsoleMessage.js |
| index a4ced8e940ca4f3ba33e30504f58321eeafd2db0..8c86d7d770a0d3d21225145edae006f3365faf86 100644 |
| --- a/Source/devtools/front_end/ConsoleMessage.js |
| +++ b/Source/devtools/front_end/ConsoleMessage.js |
| @@ -363,7 +363,9 @@ WebInspector.ConsoleMessageImpl.prototype = { |
| titleElement.createTextChild(description); |
| if (includePreview && obj.preview) { |
| titleElement.classList.add("console-object-preview"); |
| - var lossless = this._appendObjectPreview(obj, description, titleElement); |
| + if (description) |
| + titleElement.createTextChild(" "); |
| + var lossless = this._appendObjectPreview(obj, titleElement); |
| if (lossless) { |
| elem.appendChild(titleElement); |
| return; |
| @@ -379,37 +381,127 @@ WebInspector.ConsoleMessageImpl.prototype = { |
| /** |
| * @param {!WebInspector.RemoteObject} obj |
| - * @param {string} description |
| * @param {!Element} titleElement |
| * @return {boolean} true iff preview captured all information. |
| */ |
| - _appendObjectPreview: function(obj, description, titleElement) |
| + _appendObjectPreview: function(obj, titleElement) |
| { |
| var preview = obj.preview; |
| var isArray = obj.subtype === "array"; |
| + var arrayLength = isArray ? obj.arrayLength() : undefined; |
| + var properties = preview.properties; |
| - if (description) |
| - titleElement.createTextChild(" "); |
| - titleElement.createTextChild(isArray ? "[" : "{"); |
| - for (var i = 0; i < preview.properties.length; ++i) { |
| - if (i > 0) |
| - titleElement.createTextChild(", "); |
| - |
| - var property = preview.properties[i]; |
| + var elements = []; |
| + for (var i = 0; i < properties.length; ++i) { |
| + var property = properties[i]; |
| var name = property.name; |
| - if (!isArray || name != i) { |
| - if (/^\s|\s$|^$|\n/.test(name)) |
| - name = "\"" + name.replace(/\n/g, "\u21B5") + "\""; |
| - titleElement.createChild("span", "name").textContent = name; |
| - titleElement.createTextChild(": "); |
| + elements.push({ |
| + name: name, |
| + element: this._renderPropertyPreviewOrAccessor(obj, [property]) |
| + }); |
| + } |
| + |
| + this._appendArrayOrObjectPropertyElements(titleElement, elements, preview.overflow, arrayLength); |
| + return preview.lossless; |
| + }, |
| + |
| + /** |
| + * @param {!Element} parent |
| + * @param {!Array.<{name: string, element: !Element}>} propertyElements |
| + * @param {boolean} overflow |
| + * @param {number=} arrayLength |
| + */ |
| + _appendArrayOrObjectPropertyElements: function(parent, propertyElements, overflow, arrayLength) |
|
pfeldman
2014/01/23 16:19:02
This only runs for preview, right? Could you name
aandrey
2014/01/24 06:22:04
not only for preview: from _printArray also.
|
| + { |
| + const maxFlatArrayLength = 100; |
| + |
| + /** |
| + * @param {{name: string, element: !Element}} a |
| + * @param {{name: string, element: !Element}} b |
| + * @return {number} |
| + */ |
| + function comparator(a, b) |
| + { |
| + var isIndex1 = String.isArrayIndexPropertyName(a.name, arrayLength); |
| + var isIndex2 = String.isArrayIndexPropertyName(b.name, arrayLength); |
| + if (isIndex1 && isIndex2) |
| + return Number(a.name) - Number(b.name); |
| + if (isIndex1) |
| + return -1; |
| + if (isIndex2) |
| + return 1; |
| + return 0; |
| + } |
| + |
| + var isArray = typeof arrayLength === "number"; |
| + if (isArray) |
| + propertyElements.stableSort(comparator); |
|
pfeldman
2014/01/23 16:19:02
Why sorting properties? They should come in sorted
aandrey
2014/01/24 06:22:04
They are sorted according to the index in the prot
|
| + var isFlatArray = isArray && (arrayLength <= maxFlatArrayLength); |
|
pfeldman
2014/01/23 16:19:02
So we only render as flat when < 100 actual values
aandrey
2014/01/24 06:22:04
Yes. This has been the case up to now - I didn't c
|
| + |
| + parent.createTextChild(isArray ? "[" : "{"); |
| + var firstElement = true; |
| + var lastNonEmptyArrayIndex = -1; |
| + |
| + function appendCommaIfNeeded() |
| + { |
| + if (firstElement) |
| + firstElement = false; |
| + else |
| + parent.createTextChild(", "); |
| + } |
| + |
| + /** |
| + * @param {number=} index |
| + */ |
| + function appendUndefinedArrayElements(index) |
| + { |
| + if (typeof index !== "number") |
| + return; |
| + var undefinedRange = index - lastNonEmptyArrayIndex - 1; |
| + lastNonEmptyArrayIndex = index; |
| + if (undefinedRange < 1) |
| + return; |
| + appendCommaIfNeeded(); |
| + var span = parent.createChild("span", "console-formatted-undefined"); |
| + span.textContent = WebInspector.UIString("undefined × %d", undefinedRange); |
| + } |
| + |
| + /** |
| + * @param {string} name |
| + */ |
| + function appendPropertyName(name) |
| + { |
| + if (/^\s|\s$|^$|\n/.test(name)) |
| + name = "\"" + name.replace(/\n/g, "\u21B5") + "\""; |
| + parent.createChild("span", "name").textContent = name; |
| + parent.createTextChild(": "); |
| + } |
| + |
| + for (var i = 0, n = propertyElements.length; i < n; ++i) { |
| + var name = propertyElements[i].name; |
| + var element = propertyElements[i].element; |
| + var isIndex = String.isArrayIndexPropertyName(name, arrayLength); |
| + var index = isIndex ? Number(name) : 0; |
| + |
| + if (isFlatArray) { |
| + appendUndefinedArrayElements(isIndex ? index : arrayLength); |
| + appendCommaIfNeeded(); |
| + if (!isIndex) |
| + appendPropertyName(name); |
| + } else { |
| + appendCommaIfNeeded(); |
| + if (!isArray || !isIndex || index !== i) |
| + appendPropertyName(name); |
| } |
| - titleElement.appendChild(this._renderPropertyPreviewOrAccessor(obj, [property])); |
| + parent.appendChild(element); |
| } |
| - if (preview.overflow) |
| - titleElement.createChild("span").textContent = "\u2026"; |
| - titleElement.createTextChild(isArray ? "]" : "}"); |
| - return preview.lossless; |
| + if (isFlatArray) |
| + appendUndefinedArrayElements(arrayLength); |
| + |
| + if (overflow) |
| + parent.createChild("span").textContent = "\u2026"; |
| + parent.createTextChild(isArray ? "]" : "}"); |
| }, |
| /** |
| @@ -512,7 +604,7 @@ WebInspector.ConsoleMessageImpl.prototype = { |
| if (this._isOutdated || array.arrayLength() > maxFlatArrayLength) |
| this._formatParameterAsObject(array, elem, false); |
| else |
| - array.getOwnProperties(this._printArray.bind(this, array, elem)); |
| + array.getAllProperties(false, this._printArray.bind(this, array, elem)); |
| }, |
| /** |
| @@ -595,51 +687,36 @@ WebInspector.ConsoleMessageImpl.prototype = { |
| */ |
| _printArray: function(array, elem, properties) |
| { |
| - if (!properties) |
| + if (!properties) { |
| + // Fall back to object formatting. |
| + this._formatParameterAsObject(array, elem, false); |
| return; |
| + } |
| + const maxNonIndexElements = 5; |
| + var arrayLength = array.arrayLength(); |
| var elements = []; |
| + var nonIndexElements = 0; |
| for (var i = 0; i < properties.length; ++i) { |
| var property = properties[i]; |
| var name = property.name; |
| - if (isNaN(name)) |
| - continue; |
| + if (!String.isArrayIndexPropertyName(name, arrayLength)) { |
| + if (name === "length" || !property.enumerable) |
| + continue; |
| + if (++nonIndexElements > maxNonIndexElements) |
| + continue; |
| + } |
| + var element = null; |
| if (property.getter) |
| - elements[name] = this._formatAsAccessorProperty(array, [name], true); |
| + element = this._formatAsAccessorProperty(array, [name], true); |
| else if (property.value) |
| - elements[name] = this._formatAsArrayEntry(property.value); |
| - } |
| - |
| - elem.appendChild(document.createTextNode("[")); |
| - var lastNonEmptyIndex = -1; |
| - |
| - function appendUndefined(elem, index) |
| - { |
| - if (index - lastNonEmptyIndex <= 1) |
| - return; |
| - var span = elem.createChild("span", "console-formatted-undefined"); |
| - span.textContent = WebInspector.UIString("undefined × %d", index - lastNonEmptyIndex - 1); |
| - } |
| - |
| - var length = array.arrayLength(); |
| - for (var i = 0; i < length; ++i) { |
| - var element = elements[i]; |
| - if (!element) |
| - continue; |
| - |
| - if (i - lastNonEmptyIndex > 1) { |
| - appendUndefined(elem, i); |
| - elem.appendChild(document.createTextNode(", ")); |
| - } |
| - |
| - elem.appendChild(element); |
| - lastNonEmptyIndex = i; |
| - if (i < length - 1) |
| - elem.appendChild(document.createTextNode(", ")); |
| + element = this._formatAsArrayEntry(property.value); |
| + if (element) |
| + elements.push({ name: name, element: element }); |
| } |
| - appendUndefined(elem, length); |
| - elem.appendChild(document.createTextNode("]")); |
| + var overflow = (nonIndexElements > maxNonIndexElements); |
| + this._appendArrayOrObjectPropertyElements(elem, elements, overflow, arrayLength); |
| }, |
| /** |