DevTools: Fix console not showing array items inherited from prototype.
BUG=320632
R=pfeldman
Review URL: https://codereview.chromium.org/844563003
git-svn-id: svn://svn.chromium.org/blink/trunk@188228 bbb929c8-8fbe-4397-9dbb-9b2b20218538
diff --git a/LayoutTests/inspector/console/console-format-array-prototype-expected.txt b/LayoutTests/inspector/console/console-format-array-prototype-expected.txt
new file mode 100644
index 0000000..13f327b
--- /dev/null
+++ b/LayoutTests/inspector/console/console-format-array-prototype-expected.txt
@@ -0,0 +1,43 @@
+CONSOLE MESSAGE: line 9:
+CONSOLE MESSAGE: line 9: arr0
+CONSOLE MESSAGE: line 9: arr0,,,,
+CONSOLE MESSAGE: line 9: arr0,2,3
+CONSOLE MESSAGE: line 9: arr0,,,,,obj5,,,,,arr10,,,,
+CONSOLE MESSAGE: line 9: arr0,,,,,obj5,,,8,,arr10,,,,
+CONSOLE MESSAGE: line 9: 0,,,,,obj5,,,,,10,,,,
+CONSOLE MESSAGE: line 9: arr0,,,4,,obj5,,,,,arr10,,,,
+CONSOLE MESSAGE: line 9: 0,1,2,3,4,5,6,7,8,9
+CONSOLE MESSAGE: line 9: arr0,1,2,3,4,obj5,6,7,8,9,arr10
+Tests that console logging dumps array values defined on Array.prototype[].
+
+a0
+[]
+console-format-array-prototype.html:9 [0: "arr0", 10: "arr10", 5: "obj5"]
+a1
+["arr0"]
+console-format-array-prototype.html:9 ["arr0", 10: "arr10", 5: "obj5"]
+a2
+["arr0", undefined × 4]
+console-format-array-prototype.html:9 ["arr0", 10: "arr10", 5: "obj5"]
+a3
+["arr0", 2, 3]
+console-format-array-prototype.html:9 ["arr0", 2, 3, 10: "arr10", 5: "obj5"]
+a4
+["arr0", undefined × 4, "obj5", undefined × 4, "arr10", undefined × 4]
+console-format-array-prototype.html:9 ["arr0", 5: "obj5", 10: "arr10"]
+a5
+["arr0", undefined × 4, "obj5", undefined × 2, 8, undefined × 1, "arr10", undefined × 4]
+console-format-array-prototype.html:9 ["arr0", 5: "obj5", 8: 8, 10: "arr10"]
+a6
+[0, undefined × 4, "obj5", undefined × 4, 10, undefined × 4]
+console-format-array-prototype.html:9 [0, 5: "obj5", 10: 10]
+a7
+["arr0", undefined × 2, 4, undefined × 1, "obj5", undefined × 4, "arr10", undefined × 4]
+console-format-array-prototype.html:9 [3: 4, index0: 0, index1: 1, index2: 2, index3: 3, index4: 4…]
+a8
+[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+console-format-array-prototype.html:9 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10: "arr10"]
+a9
+["arr0", 1, 2, 3, 4, "obj5", 6, 7, 8, 9, "arr10"]
+console-format-array-prototype.html:9 ["arr0", 1, 2, 3, 4, "obj5", 6, 7, 8, 9, "arr10", foo: "bar"]
+
diff --git a/LayoutTests/inspector/console/console-format-array-prototype.html b/LayoutTests/inspector/console/console-format-array-prototype.html
new file mode 100644
index 0000000..c997f25
--- /dev/null
+++ b/LayoutTests/inspector/console/console-format-array-prototype.html
@@ -0,0 +1,90 @@
+<html>
+<head>
+<script src="../../http/tests/inspector/inspector-test.js"></script>
+<script src="../../http/tests/inspector/console-test.js"></script>
+<script>
+
+function log(data)
+{
+ console.log(data);
+}
+
+Array.prototype[0] = "arr0";
+Array.prototype[10] = "arr10";
+Object.defineProperty(Object.prototype, "5", {
+ value: "obj5",
+ configurable: true,
+ writable: true,
+ enumerable: false
+});
+
+function tearDown()
+{
+ delete Array.prototype[0];
+ delete Array.prototype[10];
+ delete Object.prototype[5];
+}
+
+var a0 = [];
+var a1 = []; a1.length = 1;
+var a2 = []; a2.length = 5;
+var a3 = [,2,3];
+var a4 = []; a4.length = 15;
+var a5 = []; a5.length = 15; a5[8] = 8;
+var a6 = []; a6.length = 15; a6[0] = 0; a6[10] = 10;
+var a7 = [,,,4]; a7.length = 15;
+for (var i = 0; i < 6; ++i)
+ a7["index" + i] = i;
+var a8 = [];
+for (var i = 0; i < 10; ++i)
+ a8[i] = i;
+var a9 = [];
+for (var i = 1; i < 5; ++i) {
+ a9[i] = i;
+ a9[i + 5] = i + 5;
+}
+a9.length = 11;
+a9.foo = "bar";
+
+function test()
+{
+ loopOverGlobals(0, 10);
+
+ function loopOverGlobals(current, total)
+ {
+ function advance()
+ {
+ var next = current + 1;
+ if (next === total) {
+ InspectorTest.evaluateInPage("tearDown()");
+ InspectorTest.expandConsoleMessages();
+ InspectorTest.runAfterPendingDispatches(finish);
+ } else {
+ loopOverGlobals(next, total);
+ }
+ }
+
+ function finish()
+ {
+ InspectorTest.dumpConsoleMessages(false, false, InspectorTest.textContentWithLineBreaks);
+ InspectorTest.completeTest();
+ }
+
+ InspectorTest.evaluateInConsole("a" + current);
+ InspectorTest.runAfterPendingDispatches(invokeConsoleLog);
+ function invokeConsoleLog()
+ {
+ InspectorTest.evaluateInPage("log(a" + current + ")");
+ InspectorTest.runAfterPendingDispatches(advance);
+ }
+ }
+}
+</script>
+</head>
+
+<body onload="runTest()">
+<p>
+Tests that console logging dumps array values defined on Array.prototype[].
+</p>
+</body>
+</html>
diff --git a/Source/core/inspector/InjectedScriptSource.js b/Source/core/inspector/InjectedScriptSource.js
index c03173c..00480ed 100644
--- a/Source/core/inspector/InjectedScriptSource.js
+++ b/Source/core/inspector/InjectedScriptSource.js
@@ -149,12 +149,14 @@
}
/**
- * @param {*} obj
+ * @param {number|string} obj
* @return {boolean}
*/
function isUInt32(obj)
{
- return typeof obj === "number" && obj >>> 0 === obj && (obj > 0 || 1 / obj > 0);
+ if (typeof obj === "number")
+ return obj >>> 0 === obj && (obj > 0 || 1 / obj > 0);
+ return "" + (obj >>> 0) === obj;
}
/**
@@ -167,8 +169,10 @@
if (typeof obj !== "object")
return false;
try {
- if (typeof obj.splice === "function")
- return isUInt32(obj.length);
+ if (typeof obj.splice === "function") {
+ var len = obj.length;
+ return typeof len === "number" && isUInt32(len);
+ }
} catch (e) {
}
return false;
@@ -1362,14 +1366,14 @@
preview.lossless = false;
continue;
}
- if (!descriptor.enumerable && !descriptor.isOwn)
- continue;
var name = descriptor.name;
if (name === "__proto__")
continue;
if (this.subtype === "array" && name === "length")
continue;
+ if (!descriptor.enumerable && !descriptor.isOwn && !(this.subtype === "array" && isUInt32(name)))
+ continue;
if (!("value" in descriptor)) {
preview.lossless = false;
diff --git a/Source/devtools/front_end/console/ConsoleViewMessage.js b/Source/devtools/front_end/console/ConsoleViewMessage.js
index 97dd5b2..809a405 100644
--- a/Source/devtools/front_end/console/ConsoleViewMessage.js
+++ b/Source/devtools/front_end/console/ConsoleViewMessage.js
@@ -517,14 +517,44 @@
_appendPropertiesPreview: function(parentElement, preview, object)
{
var isArray = preview.subtype === "array";
+ var arrayLength = WebInspector.RemoteObject.arrayLength(preview);
+ var properties = preview.properties;
+ if (isArray)
+ properties = properties.slice().stableSort(compareIndexesFirst);
+
+ /**
+ * @param {!RuntimeAgent.PropertyPreview} a
+ * @param {!RuntimeAgent.PropertyPreview} b
+ */
+ function compareIndexesFirst(a, b)
+ {
+ var index1 = toArrayIndex(a.name);
+ var index2 = toArrayIndex(b.name);
+ if (index1 < 0)
+ return index2 < 0 ? 0 : 1;
+ return index2 < 0 ? -1 : index1 - index2;
+ }
+
+ /**
+ * @param {string} name
+ * @return {number}
+ */
+ function toArrayIndex(name)
+ {
+ var index = name >>> 0;
+ if (String(index) === name && index < arrayLength)
+ return index;
+ return -1;
+ }
+
parentElement.createTextChild(isArray ? "[" : "{");
- for (var i = 0; i < preview.properties.length; ++i) {
+ for (var i = 0; i < properties.length; ++i) {
if (i > 0)
parentElement.createTextChild(", ");
- var property = preview.properties[i];
+ var property = properties[i];
var name = property.name;
- if (!isArray || name != i) {
+ if (!isArray || name != i || i >= arrayLength) {
if (/^\s|\s$|^$|\n/.test(name))
parentElement.createChild("span", "name").createTextChildren("\"", name.replace(/\n/g, "\u21B5"), "\"");
else
@@ -654,11 +684,11 @@
return;
}
- const maxFlatArrayLength = 100;
+ var maxFlatArrayLength = 100;
if (this._message.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));
},
/**
@@ -750,8 +780,10 @@
*/
_printArray: function(array, elem, properties)
{
- if (!properties)
+ if (!properties) {
+ this._formatParameterAsObject(array, elem, false);
return;
+ }
var elements = [];
for (var i = 0; i < properties.length; ++i) {
diff --git a/Source/devtools/front_end/sdk/RemoteObject.js b/Source/devtools/front_end/sdk/RemoteObject.js
index f6bd216..5d2844d 100644
--- a/Source/devtools/front_end/sdk/RemoteObject.js
+++ b/Source/devtools/front_end/sdk/RemoteObject.js
@@ -190,6 +190,20 @@
}
/**
+ * @param {!WebInspector.RemoteObject|!RuntimeAgent.RemoteObject|!RuntimeAgent.ObjectPreview} object
+ * @return {number}
+ */
+WebInspector.RemoteObject.arrayLength = function(object)
+{
+ if (object.subtype !== "array")
+ return 0;
+ var matches = object.description.match(/\[([0-9]+)\]/);
+ if (!matches)
+ return 0;
+ return parseInt(matches[1], 10);
+}
+
+/**
* @param {!RuntimeAgent.RemoteObject|!WebInspector.RemoteObject|number|string|boolean|undefined|null} object
* @return {!RuntimeAgent.CallArgument}
*/
@@ -624,13 +638,7 @@
*/
arrayLength: function()
{
- if (this.subtype !== "array")
- return 0;
-
- var matches = this._description.match(/\[([0-9]+)\]/);
- if (!matches)
- return 0;
- return parseInt(matches[1], 10);
+ return WebInspector.RemoteObject.arrayLength(this);
},
/**