Bug 1473901 - show shadow root mode. r=bgrins
authorBelén Albeza <balbeza@mozilla.com>
Wed, 11 Jul 2018 14:53:51 +0200
changeset 427460 98f85087087437839ab2a29bc470bf08e581bfce
parent 427459 8cce0e7ad6f3f7e91afe13e97e04fc0f0ed400c6
child 427461 54e79326147a7618d4b08f24c74e3c8ef03ba4f3
push id34306
push usercsabou@mozilla.com
push dateFri, 20 Jul 2018 21:41:18 +0000
treeherdermozilla-central@d6a5e8aea651 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbgrins
bugs1473901
milestone63.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1473901 - show shadow root mode. r=bgrins MozReview-Commit-ID: Axt9W0uX4FB
devtools/client/inspector/markup/test/browser.ini
devtools/client/inspector/markup/test/browser_markup_shadowdom_shadowroot_mode.js
devtools/client/inspector/markup/views/read-only-editor.js
devtools/server/actors/inspector/node.js
devtools/shared/fronts/node.js
devtools/shared/layout/utils.js
--- a/devtools/client/inspector/markup/test/browser.ini
+++ b/devtools/client/inspector/markup/test/browser.ini
@@ -172,16 +172,17 @@ subsuite = clipboard
 [browser_markup_shadowdom_delete.js]
 [browser_markup_shadowdom_dynamic.js]
 [browser_markup_shadowdom_hover.js]
 [browser_markup_shadowdom_maxchildren.js]
 [browser_markup_shadowdom_mutations_shadow.js]
 [browser_markup_shadowdom_navigation.js]
 [browser_markup_shadowdom_nested_pick_inspect.js]
 [browser_markup_shadowdom_noslot.js]
+[browser_markup_shadowdom_shadowroot_mode.js]
 [browser_markup_shadowdom_slotupdate.js]
 [browser_markup_tag_delete_whitespace_node.js]
 [browser_markup_tag_edit_01.js]
 [browser_markup_tag_edit_02.js]
 [browser_markup_tag_edit_03.js]
 [browser_markup_tag_edit_04-backspace.js]
 [browser_markup_tag_edit_04-delete.js]
 [browser_markup_tag_edit_05.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/markup/test/browser_markup_shadowdom_shadowroot_mode.js
@@ -0,0 +1,54 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test that the shadow root mode is displayed properly
+
+const TEST_URL = `data:text/html;charset=utf-8,
+  <closed-component></closed-component>
+  <open-component></open-component>
+
+  <script>
+    'use strict';
+
+    customElements.define("closed-component", class extends HTMLElement {
+      constructor() {
+        super();
+        this.attachShadow({mode: "closed"});
+      }
+    });
+
+    customElements.define("open-component", class extends HTMLElement {
+      constructor() {
+        super();
+        this.attachShadow({ mode: "open" });
+      }
+    });
+  </script>
+`;
+
+add_task(async function() {
+  await enableWebComponents();
+
+  const { inspector } = await openInspectorForURL(TEST_URL);
+  const {markup} = inspector;
+
+  info("Find and expand the closed-component shadow DOM host.");
+  const closedHostFront = await getNodeFront("closed-component", inspector);
+  const closedHostContainer = markup.getContainer(closedHostFront);
+  await expandContainer(inspector, closedHostContainer);
+
+  info("Check the shadow root mode");
+  const closedShadowRootContainer = closedHostContainer.getChildContainers()[0];
+  assertContainerHasText(closedShadowRootContainer, "#shadow-root (closed)");
+
+  info("Find and expand the open-component shadow DOM host.");
+  const openHostFront = await getNodeFront("open-component", inspector);
+  const openHostContainer = markup.getContainer(openHostFront);
+  await expandContainer(inspector, openHostContainer);
+
+  info("Check the shadow root mode");
+  const openShadowRootContainer = openHostContainer.getChildContainers()[0];
+  assertContainerHasText(openShadowRootContainer, "#shadow-root (open)");
+});
--- a/devtools/client/inspector/markup/views/read-only-editor.js
+++ b/devtools/client/inspector/markup/views/read-only-editor.js
@@ -16,17 +16,17 @@ function ReadOnlyEditor(container, node)
 
   if (node.isPseudoElement) {
     this.tag.classList.add("theme-fg-color5");
     this.tag.textContent = node.isBeforePseudoElement ? "::before" : "::after";
   } else if (node.nodeType == nodeConstants.DOCUMENT_TYPE_NODE) {
     this.elt.classList.add("comment", "doctype");
     this.tag.textContent = node.doctypeString;
   } else if (node.isShadowRoot) {
-    this.tag.textContent = "#shadow-root";
+    this.tag.textContent = `#shadow-root (${node.shadowRootMode})`;
   } else {
     this.tag.textContent = node.nodeName;
   }
 
   // Make the "tag" part of this editor focusable.
   this.tag.setAttribute("tabindex", "-1");
 }
 
--- a/devtools/server/actors/inspector/node.js
+++ b/devtools/server/actors/inspector/node.js
@@ -19,16 +19,17 @@ loader.lazyRequireGetter(this, "findCssS
 loader.lazyRequireGetter(this, "isAfterPseudoElement", "devtools/shared/layout/utils", true);
 loader.lazyRequireGetter(this, "isAnonymous", "devtools/shared/layout/utils", true);
 loader.lazyRequireGetter(this, "isBeforePseudoElement", "devtools/shared/layout/utils", true);
 loader.lazyRequireGetter(this, "isDirectShadowHostChild", "devtools/shared/layout/utils", true);
 loader.lazyRequireGetter(this, "isNativeAnonymous", "devtools/shared/layout/utils", true);
 loader.lazyRequireGetter(this, "isShadowAnonymous", "devtools/shared/layout/utils", true);
 loader.lazyRequireGetter(this, "isShadowHost", "devtools/shared/layout/utils", true);
 loader.lazyRequireGetter(this, "isShadowRoot", "devtools/shared/layout/utils", true);
+loader.lazyRequireGetter(this, "getShadowRootMode", "devtools/shared/layout/utils", true);
 loader.lazyRequireGetter(this, "isXBLAnonymous", "devtools/shared/layout/utils", true);
 
 loader.lazyRequireGetter(this, "InspectorActorUtils", "devtools/server/actors/inspector/utils");
 loader.lazyRequireGetter(this, "LongStringActor", "devtools/server/actors/string", true);
 loader.lazyRequireGetter(this, "getFontPreviewData", "devtools/server/actors/styles", true);
 loader.lazyRequireGetter(this, "CssLogic", "devtools/server/actors/inspector/css-logic", true);
 loader.lazyRequireGetter(this, "EventParsers", "devtools/server/actors/inspector/event-parsers", true);
 
@@ -127,16 +128,17 @@ const NodeActor = protocol.ActorClassWit
       attrs: this.writeAttrs(),
       isBeforePseudoElement: isBeforePseudoElement(this.rawNode),
       isAfterPseudoElement: isAfterPseudoElement(this.rawNode),
       isAnonymous: isAnonymous(this.rawNode),
       isNativeAnonymous: isNativeAnonymous(this.rawNode),
       isXBLAnonymous: isXBLAnonymous(this.rawNode),
       isShadowAnonymous: isShadowAnonymous(this.rawNode),
       isShadowRoot: shadowRoot,
+      shadowRootMode: getShadowRootMode(this.rawNode),
       isShadowHost: isShadowHost(this.rawNode),
       isDirectShadowHostChild: isDirectShadowHostChild(this.rawNode),
       pseudoClassLocks: this.writePseudoClassLocks(),
 
       isDisplayed: this.isDisplayed,
       isInHTMLDocument: this.rawNode.ownerDocument &&
         this.rawNode.ownerDocument.contentType === "text/html",
       hasEventListeners: this._hasEventListeners,
--- a/devtools/shared/fronts/node.js
+++ b/devtools/shared/fronts/node.js
@@ -306,16 +306,20 @@ const NodeFront = FrontClassWithSpec(nod
   get isDocumentElement() {
     return !!this._form.isDocumentElement;
   },
 
   get isShadowRoot() {
     return this._form.isShadowRoot;
   },
 
+  get shadowRootMode() {
+    return this._form.shadowRootMode;
+  },
+
   get isShadowHost() {
     return this._form.isShadowHost;
   },
 
   get isDirectShadowHostChild() {
     return this._form.isDirectShadowHostChild;
   },
 
--- a/devtools/shared/layout/utils.js
+++ b/devtools/shared/layout/utils.js
@@ -604,16 +604,27 @@ exports.isTemplateElement = isTemplateEl
  * @return {Boolean}
  */
 function isShadowRoot(node) {
   const isFragment = node.nodeType === Node.DOCUMENT_FRAGMENT_NODE;
   return isFragment && !!node.host;
 }
 exports.isShadowRoot = isShadowRoot;
 
+/*
+ * Gets the shadow root mode (open or closed).
+ *
+ * @param {DOMNode} node
+ * @return {String|null}
+ */
+function getShadowRootMode(node) {
+  return isShadowRoot(node) ? node.mode : null;
+}
+exports.getShadowRootMode = getShadowRootMode;
+
 /**
  * Determine whether a node is a shadow host, ie. an element that has a shadowRoot
  * attached to itself.
  *
  * @param {DOMNode} node
  * @return {Boolean}
  */
 function isShadowHost(node) {