Bug 1465873 - part4: Update document-walker::parentNode() to return shadow roots;r=bgrins
MozReview-Commit-ID: GwAl9DCT3Fs
--- a/devtools/server/actors/inspector/document-walker.js
+++ b/devtools/server/actors/inspector/document-walker.js
@@ -1,16 +1,17 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {Cc, Ci, Cu} = require("chrome");
+loader.lazyRequireGetter(this, "isShadowRoot", "devtools/shared/layout/utils", true);
loader.lazyRequireGetter(this, "nodeFilterConstants", "devtools/shared/dom-node-filter-constants");
loader.lazyRequireGetter(this, "standardTreeWalkerFilter", "devtools/server/actors/inspector/utils", true);
// SKIP_TO_* arguments are used with the DocumentWalker, driving the strategy to use if
// the starting node is incompatible with the filter function of the walker.
const SKIP_TO_PARENT = "SKIP_TO_PARENT";
const SKIP_TO_SIBLING = "SKIP_TO_SIBLING";
@@ -68,16 +69,27 @@ DocumentWalker.prototype = {
get currentNode() {
return this.walker.currentNode;
},
set currentNode(val) {
this.walker.currentNode = val;
},
parentNode: function() {
+ if (isShadowRoot(this.currentNode)) {
+ this.currentNode = this.currentNode.host;
+ return this.currentNode;
+ }
+
+ const parentNode = this.currentNode.parentNode;
+ // deep-tree-walker currently does not return shadowRoot elements as parentNodes.
+ if (parentNode && isShadowRoot(parentNode)) {
+ this.currentNode = parentNode;
+ return this.currentNode;
+ }
return this.walker.parentNode();
},
nextNode: function() {
const node = this.walker.currentNode;
if (!node) {
return null;
}
--- a/devtools/server/actors/inspector/walker.js
+++ b/devtools/server/actors/inspector/walker.js
@@ -436,37 +436,42 @@ var WalkerActor = protocol.ActorClassWit
documentElement: function(node) {
const elt = isNodeDead(node)
? this.rootDoc.documentElement
: nodeDocument(node.rawNode).documentElement;
return this._ref(elt);
},
parentNode: function(node) {
+ const parent = this.rawParentNode(node);
+ if (parent) {
+ return this._ref(parent);
+ }
+
+ return null;
+ },
+
+ rawParentNode: function(node) {
let parent;
try {
// If the node is the child of a shadow host, we can not use an anonymous walker to
// get the shadow host parent.
const walker = isDirectShadowHostChild(node.rawNode)
? this.getNonAnonymousWalker(node.rawNode)
: this.getDocumentWalker(node.rawNode);
parent = walker.parentNode();
} catch (e) {
// When getting the parent node for a child of a non-slotted shadow host child,
// walker.parentNode() will throw if the walker is anonymous, because non-slotted
// shadow host children are not accessible anywhere in the anonymous tree.
const walker = this.getNonAnonymousWalker(node.rawNode);
parent = walker.parentNode();
}
- if (parent) {
- return this._ref(parent);
- }
-
- return null;
+ return parent;
},
/**
* If the given NodeActor only has a single text node as a child with a text
* content small enough to be inlined, return that child's NodeActor.
*
* @param NodeActor node
*/
@@ -567,27 +572,27 @@ var WalkerActor = protocol.ActorClassWit
/**
* Add any nodes between `node` and the walker's root node that have not
* yet been seen by the client.
*/
ensurePathToRoot: function(node, newParents = new Set()) {
if (!node) {
return newParents;
}
- const walker = this.getDocumentWalker(node.rawNode);
- let cur;
- while ((cur = walker.parentNode())) {
- const parent = this.getNode(cur);
- if (!parent) {
- // This parent didn't exist, so hasn't been seen by the client yet.
- newParents.add(this._ref(cur));
- } else {
+ let parent = this.rawParentNode(node);
+ while (parent) {
+ let parentActor = this.getNode(parent);
+ if (parentActor) {
// This parent did exist, so the client knows about it.
return newParents;
}
+ // This parent didn't exist, so hasn't been seen by the client yet.
+ parentActor = this._ref(parent);
+ newParents.add(parentActor);
+ parent = this.rawParentNode(parentActor);
}
return newParents;
},
/**
* Return the number of children under the provided NodeActor.
*
* @param NodeActor node