Bug 1311168 - Handle document fragment in grip array rep; r=Honza draft
authorNicolas Chevobbe <chevobbe.nicolas@gmail.com>
Sun, 23 Oct 2016 19:31:41 +0200
changeset 435313 9a2eee2d7cec16eb3a27938fd5e0174ab0e5989e
parent 435182 f13e90d496cf1bc6dfc4fd398da33e4afe785bde
child 536275 b5733ec4428db5a8b41e886e3aaa6c7cd9660388
push id34999
push userchevobbe.nicolas@gmail.com
push dateTue, 08 Nov 2016 12:22:28 +0000
reviewersHonza
bugs1311168
milestone52.0a1
Bug 1311168 - Handle document fragment in grip array rep; r=Honza MozReview-Commit-ID: Cq2YyKlMjjQ
devtools/client/shared/components/reps/grip-array.js
devtools/client/shared/components/test/mochitest/test_reps_grip-array.html
--- a/devtools/client/shared/components/reps/grip-array.js
+++ b/devtools/client/shared/components/reps/grip-array.js
@@ -25,70 +25,83 @@ define(function (require, exports, modul
 
     propTypes: {
       object: React.PropTypes.object.isRequired,
       mode: React.PropTypes.string,
       provider: React.PropTypes.object,
     },
 
     getLength: function (grip) {
-      return grip.preview ? grip.preview.length : 0;
+      if (!grip.preview) {
+        return 0;
+      }
+
+      return grip.preview.length || grip.preview.childNodesLength || 0;
     },
 
     getTitle: function (object, context) {
       let objectLink = this.props.objectLink || span;
       if (this.props.mode != "tiny") {
         return objectLink({
           object: object
         }, object.class + " ");
       }
       return "";
     },
 
+    getPreviewItems: function (grip) {
+      if (!grip.preview) {
+        return null;
+      }
+
+      return grip.preview.items || grip.preview.childNodes || null;
+    },
+
     arrayIterator: function (grip, max) {
       let items = [];
+      const gripLength = this.getLength(grip);
 
-      if (!grip.preview || !grip.preview.length) {
+      if (!gripLength) {
         return items;
       }
 
-      let array = grip.preview.items;
-      if (!array) {
+      const previewItems = this.getPreviewItems(grip);
+      if (!previewItems) {
         return items;
       }
 
       let delim;
-      // number of grip.preview.items is limited to 10, but we may have more
-      // items in grip-array
-      let delimMax = grip.preview.length > array.length ?
-        array.length : array.length - 1;
+      // number of grip preview items is limited to 10, but we may have more
+      // items in grip-array.
+      let delimMax = gripLength > previewItems.length ?
+        previewItems.length : previewItems.length - 1;
       let provider = this.props.provider;
 
-      for (let i = 0; i < array.length && i < max; i++) {
+      for (let i = 0; i < previewItems.length && i < max; i++) {
         try {
-          let itemGrip = array[i];
+          let itemGrip = previewItems[i];
           let value = provider ? provider.getValue(itemGrip) : itemGrip;
 
           delim = (i == delimMax ? "" : ", ");
 
           items.push(GripArrayItem(Object.assign({}, this.props, {
             object: value,
             delim: delim
           })));
         } catch (exc) {
           items.push(GripArrayItem(Object.assign({}, this.props, {
             object: exc,
             delim: delim
           })));
         }
       }
-      if (array.length > max || grip.preview.length > array.length) {
+      if (previewItems.length > max || gripLength > previewItems.length) {
         let objectLink = this.props.objectLink || span;
-        let leftItemNum = grip.preview.length - max > 0 ?
-          grip.preview.length - max : grip.preview.length - array.length;
+        let leftItemNum = gripLength - max > 0 ?
+          gripLength - max : gripLength - previewItems.length;
         items.push(Caption({
           object: objectLink({
             object: this.props.object
           }, leftItemNum + " more…")
         }));
       }
 
       return items;
@@ -165,17 +178,21 @@ define(function (require, exports, modul
     }
   }));
 
   function supportsObject(grip, type) {
     if (!isGrip(grip)) {
       return false;
     }
 
-    return (grip.preview && grip.preview.kind == "ArrayLike");
+    return (grip.preview && (
+        grip.preview.kind == "ArrayLike" ||
+        type === "DocumentFragment"
+      )
+    );
   }
 
   // Exports from this module
   exports.GripArray = {
     rep: GripArray,
     supportsObject: supportsObject
   };
 });
--- a/devtools/client/shared/components/test/mochitest/test_reps_grip-array.html
+++ b/devtools/client/shared/components/test/mochitest/test_reps_grip-array.html
@@ -32,16 +32,17 @@ window.onload = Task.async(function* () 
     // Test property iterator
     yield testMaxProps();
     yield testMoreThanShortMaxProps();
     yield testMoreThanLongMaxProps();
     yield testRecursiveArray();
     yield testPreviewLimit();
     yield testNamedNodeMap();
     yield testNodeList();
+    yield testDocumentFragment();
   } catch(e) {
     ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
   } finally {
     SimpleTest.finish();
   }
 
   function testBasic() {
     // Test array: `[]`
@@ -267,16 +268,48 @@ window.onload = Task.async(function* () 
         mode: "long",
         expectedOutput: defaultOutput,
       }
     ];
 
     testRepRenderModes(modeTests, testName, componentUnderTest, getGripStub(testName));
   }
 
+  function testDocumentFragment() {
+    const testName = "testDocumentFragment";
+
+    const defaultOutput = "DocumentFragment [ li#li-0.list-element, " +
+      "li#li-1.list-element, li#li-2.list-element, 2 more… ]";
+
+    const longOutput = "DocumentFragment [ " +
+      "li#li-0.list-element, li#li-1.list-element, li#li-2.list-element, " +
+      "li#li-3.list-element, li#li-4.list-element ]";
+
+    const modeTests = [
+      {
+        mode: undefined,
+        expectedOutput: defaultOutput,
+      },
+      {
+        mode: "tiny",
+        expectedOutput: `[5]`,
+      },
+      {
+        mode: "short",
+        expectedOutput: defaultOutput,
+      },
+      {
+        mode: "long",
+        expectedOutput: longOutput,
+      }
+    ];
+
+    testRepRenderModes(modeTests, testName, componentUnderTest, getGripStub(testName));
+  }
+
   function getGripStub(functionName) {
     switch (functionName) {
       case "testBasic":
         return {
           "type": "object",
           "class": "Array",
           "actor": "server1.conn0.obj35",
           "extensible": true,
@@ -407,77 +440,78 @@ window.onload = Task.async(function* () 
                   "kind": "ArrayLike",
                   "length": 1
                 }
               }
             ]
           }
         };
 
-        case "testNamedNodeMap":
-          return {
-            "type": "object",
-            "class": "NamedNodeMap",
-            "actor": "server1.conn3.obj42",
-            "extensible": true,
-            "frozen": false,
-            "sealed": false,
-            "ownPropertyLength": 6,
-            "preview": {
-              "kind": "ArrayLike",
-              "length": 3,
-              "items": [
-                {
-                  "type": "object",
-                  "class": "Attr",
-                  "actor": "server1.conn3.obj43",
-                  "extensible": true,
-                  "frozen": false,
-                  "sealed": false,
-                  "ownPropertyLength": 0,
-                  "preview": {
-                    "kind": "DOMNode",
-                    "nodeType": 2,
-                    "nodeName": "class",
-                    "value": "myclass"
-                  }
-                },
-                {
-                  "type": "object",
-                  "class": "Attr",
-                  "actor": "server1.conn3.obj44",
-                  "extensible": true,
-                  "frozen": false,
-                  "sealed": false,
-                  "ownPropertyLength": 0,
-                  "preview": {
-                    "kind": "DOMNode",
-                    "nodeType": 2,
-                    "nodeName": "cellpadding",
-                    "value": "7"
-                  }
-                },
-                {
-                  "type": "object",
-                  "class": "Attr",
-                  "actor": "server1.conn3.obj44",
-                  "extensible": true,
-                  "frozen": false,
-                  "sealed": false,
-                  "ownPropertyLength": 0,
-                  "preview": {
-                    "kind": "DOMNode",
-                    "nodeType": 2,
-                    "nodeName": "border",
-                    "value": "3"
-                  }
+      case "testNamedNodeMap":
+        return {
+          "type": "object",
+          "class": "NamedNodeMap",
+          "actor": "server1.conn3.obj42",
+          "extensible": true,
+          "frozen": false,
+          "sealed": false,
+          "ownPropertyLength": 6,
+          "preview": {
+            "kind": "ArrayLike",
+            "length": 3,
+            "items": [
+              {
+                "type": "object",
+                "class": "Attr",
+                "actor": "server1.conn3.obj43",
+                "extensible": true,
+                "frozen": false,
+                "sealed": false,
+                "ownPropertyLength": 0,
+                "preview": {
+                  "kind": "DOMNode",
+                  "nodeType": 2,
+                  "nodeName": "class",
+                  "value": "myclass"
                 }
-              ]
-            }
-          };
+              },
+              {
+                "type": "object",
+                "class": "Attr",
+                "actor": "server1.conn3.obj44",
+                "extensible": true,
+                "frozen": false,
+                "sealed": false,
+                "ownPropertyLength": 0,
+                "preview": {
+                  "kind": "DOMNode",
+                  "nodeType": 2,
+                  "nodeName": "cellpadding",
+                  "value": "7"
+                }
+              },
+              {
+                "type": "object",
+                "class": "Attr",
+                "actor": "server1.conn3.obj44",
+                "extensible": true,
+                "frozen": false,
+                "sealed": false,
+                "ownPropertyLength": 0,
+                "preview": {
+                  "kind": "DOMNode",
+                  "nodeType": 2,
+                  "nodeName": "border",
+                  "value": "3"
+                }
+              }
+            ]
+          }
+        };
+
       case "testNodeList":
         return {
           "type": "object",
           "actor": "server1.conn1.child1/obj51",
           "class": "NodeList",
           "extensible": true,
           "frozen": false,
           "sealed": false,
@@ -544,15 +578,130 @@ window.onload = Task.async(function* () 
                     "type": "button"
                   },
                   "attributesLength": 3
                 }
               }
             ]
           }
         };
+
+      case "testDocumentFragment":
+        return {
+          "type": "object",
+          "actor": "server1.conn1.child1/obj45",
+          "class": "DocumentFragment",
+          "extensible": true,
+          "frozen": false,
+          "sealed": false,
+          "ownPropertyLength": 0,
+          "preview": {
+            "kind": "DOMNode",
+            "nodeType": 11,
+            "nodeName": "#document-fragment",
+            "childNodesLength": 5,
+            "childNodes": [
+              {
+                "type": "object",
+                "actor": "server1.conn1.child1/obj46",
+                "class": "HTMLLIElement",
+                "extensible": true,
+                "frozen": false,
+                "sealed": false,
+                "ownPropertyLength": 0,
+                "preview": {
+                  "kind": "DOMNode",
+                  "nodeType": 1,
+                  "nodeName": "li",
+                  "attributes": {
+                    "id": "li-0",
+                    "class": "list-element"
+                  },
+                  "attributesLength": 2
+                }
+              },
+              {
+                "type": "object",
+                "actor": "server1.conn1.child1/obj47",
+                "class": "HTMLLIElement",
+                "extensible": true,
+                "frozen": false,
+                "sealed": false,
+                "ownPropertyLength": 0,
+                "preview": {
+                  "kind": "DOMNode",
+                  "nodeType": 1,
+                  "nodeName": "li",
+                  "attributes": {
+                    "id": "li-1",
+                    "class": "list-element"
+                  },
+                  "attributesLength": 2
+                }
+              },
+              {
+                "type": "object",
+                "actor": "server1.conn1.child1/obj48",
+                "class": "HTMLLIElement",
+                "extensible": true,
+                "frozen": false,
+                "sealed": false,
+                "ownPropertyLength": 0,
+                "preview": {
+                  "kind": "DOMNode",
+                  "nodeType": 1,
+                  "nodeName": "li",
+                  "attributes": {
+                    "id": "li-2",
+                    "class": "list-element"
+                  },
+                  "attributesLength": 2
+                }
+              },
+              {
+                "type": "object",
+                "actor": "server1.conn1.child1/obj49",
+                "class": "HTMLLIElement",
+                "extensible": true,
+                "frozen": false,
+                "sealed": false,
+                "ownPropertyLength": 0,
+                "preview": {
+                  "kind": "DOMNode",
+                  "nodeType": 1,
+                  "nodeName": "li",
+                  "attributes": {
+                    "id": "li-3",
+                    "class": "list-element"
+                  },
+                  "attributesLength": 2
+                }
+              },
+              {
+                "type": "object",
+                "actor": "server1.conn1.child1/obj50",
+                "class": "HTMLLIElement",
+                "extensible": true,
+                "frozen": false,
+                "sealed": false,
+                "ownPropertyLength": 0,
+                "preview": {
+                  "kind": "DOMNode",
+                  "nodeType": 1,
+                  "nodeName": "li",
+                  "attributes": {
+                    "id": "li-4",
+                    "class": "list-element"
+                  },
+                  "attributesLength": 2
+                }
+              }
+            ]
+          }
+        };
     }
+    return null;
   }
 });
 </script>
 </pre>
 </body>
 </html>