Bug 1053898 - Update WalkerActor to return shadowRoot as child of host element;r=bgrins draft
authorJulian Descottes <jdescottes@mozilla.com>
Mon, 19 Mar 2018 10:33:07 +0100
changeset 773664 4e7c5c219e0c7db9324fd363f4597a653bcae109
parent 773386 b32b14c180d94082ae8ecdb6195daa6f44f40209
child 773665 a71f90edb139122d0561b4a51ef42082e64e381e
push id104269
push userjdescottes@mozilla.com
push dateWed, 28 Mar 2018 08:16:27 +0000
reviewersbgrins
bugs1053898
milestone61.0a1
Bug 1053898 - Update WalkerActor to return shadowRoot as child of host element;r=bgrins This changeset allows to display a #document-fragment as the child of a custom element that has a shadowRoot. MozReview-Commit-ID: 59wbnjz40I3
devtools/server/actors/inspector/walker.js
--- a/devtools/server/actors/inspector/walker.js
+++ b/devtools/server/actors/inspector/walker.js
@@ -197,17 +197,26 @@ var WalkerActor = protocol.ActorClassWit
     return "[WalkerActor " + this.actorID + "]";
   },
 
   getDocumentWalker: function(node, whatToShow, skipTo) {
     // Allow native anon content (like <video> controls) if preffed on
     let filter = this.showAllAnonymousContent
                     ? allAnonymousContentTreeWalkerFilter
                     : standardTreeWalkerFilter;
-    return new DocumentWalker(node, this.rootWin, {whatToShow, filter, skipTo});
+
+    return new DocumentWalker(node, this.rootWin,
+      {whatToShow, filter, skipTo, showAnonymousContent: true});
+  },
+
+  getNonAnonymousWalker: function(node, whatToShow, skipTo) {
+    let nodeFilter = standardTreeWalkerFilter;
+
+    return new DocumentWalker(node, this.rootWin,
+      {whatToShow, nodeFilter, skipTo, showAnonymousContent: false});
   },
 
   destroy: function() {
     if (this._destroyed) {
       return;
     }
     this._destroyed = true;
     protocol.Actor.prototype.destroy.call(this);
@@ -571,22 +580,42 @@ var WalkerActor = protocol.ActorClassWit
     if (options.center && options.start) {
       throw Error("Can't specify both 'center' and 'start' options.");
     }
     let maxNodes = options.maxNodes || -1;
     if (maxNodes == -1) {
       maxNodes = Number.MAX_VALUE;
     }
 
+    let isShadowHost = !!node.rawNode.shadowRoot;
+
+    if (isShadowHost) {
+      let shadowRoot = this._ref(node.rawNode.shadowRoot);
+      return {
+        hasFirst: true,
+        hasLast: true,
+        nodes: [shadowRoot],
+      };
+    }
+
+    let isShadowRoot = !!node.rawNode.host;
     // We're going to create a few document walkers with the same filter,
     // make it easier.
     let getFilteredWalker = documentWalkerNode => {
       let { whatToShow } = options;
       // Use SKIP_TO_SIBLING to force the walker to use a sibling of the provided node
       // in case this one is incompatible with the walker's filter function.
+      if (isShadowRoot) {
+        // Do not fetch anonymous children for shadow roots. If the host element has an
+        // ::after pseudo element, a walker on the last child of the shadow root will
+        // jump to the ::after element, which is not a child of the shadow root.
+        // TODO: Should rather use an anonymous walker with a new dedicated filter.
+        return this.getNonAnonymousWalker(documentWalkerNode, whatToShow,
+          SKIP_TO_SIBLING);
+      }
       return this.getDocumentWalker(documentWalkerNode, whatToShow, SKIP_TO_SIBLING);
     };
 
     // Need to know the first and last child.
     let rawNode = node.rawNode;
     let firstChild = getFilteredWalker(rawNode).firstChild();
     let lastChild = getFilteredWalker(rawNode).lastChild();