Bug 1468402 - Part 1: Add isSubgrid and subgridParentNode to the grid actor form. r=pbro
☠☠ backed out by 0647eae6a6e6 ☠ ☠
authorGabriel Luong <gabriel.luong@gmail.com>
Tue, 30 Apr 2019 00:50:47 -0400
changeset 473573 567911d83bda7ad05d88ce584e9a29000fdd4b52
parent 473572 bfb8f26e725bd8b2abd17c4dbcc3d4ffe2cf280c
child 473574 63f40ac370c63ec1aae568a569a25f768998b998
push id113091
push usergabriel.luong@gmail.com
push dateMon, 13 May 2019 16:23:11 +0000
treeherdermozilla-inbound@6685fd957302 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspbro
bugs1468402
milestone68.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 1468402 - Part 1: Add isSubgrid and subgridParentNode to the grid actor form. r=pbro Differential Revision: https://phabricator.services.mozilla.com/D29317
devtools/server/actors/layout.js
devtools/shared/fronts/layout.js
--- a/devtools/server/actors/layout.js
+++ b/devtools/server/actors/layout.js
@@ -1,15 +1,16 @@
 /* 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 { Cu } = require("chrome");
+const Services = require("Services");
 const { Actor, ActorClassWithSpec } = require("devtools/shared/protocol");
 const {
   flexboxSpec,
   flexItemSpec,
   gridSpec,
   layoutSpec,
 } = require("devtools/shared/specs/layout");
 const { SHOW_ELEMENT } = require("devtools/shared/dom-node-filter-constants");
@@ -17,16 +18,19 @@ const { getStringifiableFragments } =
   require("devtools/server/actors/utils/css-grid-utils");
 
 loader.lazyRequireGetter(this, "CssLogic", "devtools/server/actors/inspector/css-logic", true);
 loader.lazyRequireGetter(this, "getCSSStyleRules", "devtools/shared/inspector/css-logic", true);
 loader.lazyRequireGetter(this, "isCssPropertyKnown", "devtools/server/actors/css-properties", true);
 loader.lazyRequireGetter(this, "parseDeclarations", "devtools/shared/css/parsing-utils", true);
 loader.lazyRequireGetter(this, "nodeConstants", "devtools/shared/dom-node-constants");
 
+const SUBGRID_ENABLED =
+  Services.prefs.getBoolPref("layout.css.grid-template-subgrid-value.enabled");
+
 /**
  * Set of actors the expose the CSS layout information to the devtools protocol clients.
  *
  * The |Layout| actor is the main entry point. It is used to get various CSS
  * layout-related information from the document.
  *
  * The |Flexbox| actor provides the container node information to inspect the flexbox
  * container. It is also used to return an array of |FlexItem| actors which provide the
@@ -253,42 +257,68 @@ const GridActor = ActorClassWithSpec(gri
    * @param  {DOMNode} containerEl
    *         The grid container element.
    */
   initialize(layoutActor, containerEl) {
     Actor.prototype.initialize.call(this, layoutActor.conn);
 
     this.containerEl = containerEl;
     this.walker = layoutActor.walker;
+    this.computedStyle = CssLogic.getComputedStyle(this.containerEl);
+
+    if (SUBGRID_ENABLED) {
+      const { gridTemplateColumns, gridTemplateRows } = this.computedStyle;
+      this.isSubgrid = gridTemplateRows === "subgrid" ||
+                       gridTemplateColumns === "subgrid";
+
+      if (this.isSubgrid) {
+        // The parent grid container for the subgrid.
+        this.parentEl = findGridParentContainerForNode(this.containerEl, this.walker);
+      }
+    }
   },
 
   destroy() {
     Actor.prototype.destroy.call(this);
 
+    this.computedStyle = null;
     this.containerEl = null;
     this.gridFragments = null;
+    this.isSubgrid = null;
+    this.parentEl = null;
     this.walker = null;
   },
 
   form() {
     // Seralize the grid fragment data into JSON so protocol.js knows how to write
     // and read the data.
     const gridFragments = this.containerEl.getGridFragments();
     this.gridFragments = getStringifiableFragments(gridFragments);
 
     // Record writing mode and text direction for use by the grid outline.
-    const { direction, writingMode } = CssLogic.getComputedStyle(this.containerEl);
+    const { direction, writingMode } = this.computedStyle;
 
     const form = {
       actor: this.actorID,
       direction,
       gridFragments: this.gridFragments,
       writingMode,
     };
 
+    if (SUBGRID_ENABLED && this.isSubgrid) {
+      form.isSubgrid = this.isSubgrid;
+
+      // If the WalkerActor already knows the parent grid element, then also return its
+      // ActorID so we avoid the client from doing another round trip to get it in many
+      // cases.
+      if (this.walker.hasNode(this.parentEl)) {
+        form.parentGridNodeActorID = this.walker.getNode(this.parentEl).actorID;
+      }
+    }
+
     // If the WalkerActor already knows the container element, then also return its
     // ActorID so we avoid the client from doing another round trip to get it in many
     // cases.
     if (this.walker.hasNode(this.containerEl)) {
       form.containerNodeActorID = this.walker.getNode(this.containerEl).actorID;
     }
 
     return form;
--- a/devtools/shared/fronts/layout.js
+++ b/devtools/shared/fronts/layout.js
@@ -108,26 +108,57 @@ class GridFront extends FrontClassWithSp
   /**
    * Getter for the grid fragments data.
    */
   get gridFragments() {
     return this._form.gridFragments;
   }
 
   /**
+   * Get whether or not the grid is a subgrid.
+   */
+  get isSubgrid() {
+    return !!this._form.isSubgrid;
+  }
+
+  /**
    * Get the writing mode of the grid container.
    * Added in Firefox 60.
    */
   get writingMode() {
     if (!this._form.writingMode) {
       return "horizontal-tb";
     }
 
     return this._form.writingMode;
   }
+
+  /**
+   * For a subgrid, returns the NodeFront of the parent grid container.
+   *
+   * @param  {WalkerFront} walker
+   *         Client side of the DOM walker.
+   * @return {NodeFront} of the parent grid container.
+   */
+  async getParentGridNode(walker) {
+    if (this._form.parentGridNodeActorID) {
+      return this.conn.getActor(this._form.parentGridNodeActorID);
+    }
+
+    // If the parentGridNodeActorID wasn't set, that means the nodeFront for this
+    // subgrid's parent grid container hasn't been seen by the walker yet.
+    // So, get the nodeFront from the server.
+    try {
+      return await walker.getNodeFromActor(this.actorID, ["parentEl"]);
+    } catch (e) {
+      // This call might fail if called asynchrously after the toolbox is finished
+      // closing.
+      return null;
+    }
+  }
 }
 
 class LayoutFront extends FrontClassWithSpec(layoutSpec) {
 }
 
 exports.FlexboxFront = FlexboxFront;
 registerFront(FlexboxFront);
 exports.FlexItemFront = FlexItemFront;