Web Inspector: [Flexbox] Add instrumentation/protocol bits for flex layout containers
https://bugs.webkit.org/show_bug.cgi?id=235454

Reviewed by Devin Rousso.

Source/JavaScriptCore:

* inspector/protocol/CSS.json:

Source/WebCore:

Added tests in inspector/css/nodeLayoutContextTypeChanged.html.

Add instrumentation to RenderFlexibleBox to observe elements becoming/ceasing to be flex containers. We only
instrument RenderFlexibleBox created with an Element, not a Document, since all anonymous nodes will have their
document passed, which means we would attempt to track multiple different nodes against the same document,
resulting in unexpected results. Conversely, we only instrument in the destructor for non-anonymous nodes.

* inspector/agents/InspectorCSSAgent.cpp:
(WebCore::InspectorCSSAgent::layoutContextTypeForRenderer):
* rendering/RenderFlexibleBox.cpp:
(WebCore::RenderFlexibleBox::RenderFlexibleBox):
(WebCore::RenderFlexibleBox::~RenderFlexibleBox):

Source/WebInspectorUI:

* UserInterface/Models/DOMNode.js:

LayoutTests:

* inspector/css/nodeLayoutContextTypeChanged-expected.txt:
* inspector/css/nodeLayoutContextTypeChanged.html:


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@288492 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 25e227b..a375555 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,13 @@
+2022-01-24  Patrick Angle  <pangle@apple.com>
+
+        Web Inspector: [Flexbox] Add instrumentation/protocol bits for flex layout containers
+        https://bugs.webkit.org/show_bug.cgi?id=235454
+
+        Reviewed by Devin Rousso.
+
+        * inspector/css/nodeLayoutContextTypeChanged-expected.txt:
+        * inspector/css/nodeLayoutContextTypeChanged.html:
+
 2022-01-24  Eric Carlson  <eric.carlson@apple.com>
 
         REGRESSION (iOS 15): HTMLAudioElement fails to load new audio when device is locked or safari is in background
diff --git a/LayoutTests/inspector/css/nodeLayoutContextTypeChanged-expected.txt b/LayoutTests/inspector/css/nodeLayoutContextTypeChanged-expected.txt
index 43ecbf5..9ba2d83 100644
--- a/LayoutTests/inspector/css/nodeLayoutContextTypeChanged-expected.txt
+++ b/LayoutTests/inspector/css/nodeLayoutContextTypeChanged-expected.txt
@@ -10,3 +10,15 @@
 PASS: Layout context should be `null`.
 PASS: Layout context should now be `grid`.
 
+-- Running test case: CSS.nodeLayoutContextTypeChanged.FlexToNonFlex
+PASS: Layout context should be `flex`.
+PASS: Layout context should now be `null`.
+
+-- Running test case: CSS.nodeLayoutContextTypeChanged.NonFlexToFlex
+PASS: Layout context should be `null`.
+PASS: Layout context should now be `flex`.
+
+-- Running test case: CSS.nodeLayoutContextTypeChanged.GridToFlex
+PASS: Layout context should now be `grid`.
+PASS: Layout context should now be `flex`.
+
diff --git a/LayoutTests/inspector/css/nodeLayoutContextTypeChanged.html b/LayoutTests/inspector/css/nodeLayoutContextTypeChanged.html
index 0499d72..e63d1f1 100644
--- a/LayoutTests/inspector/css/nodeLayoutContextTypeChanged.html
+++ b/LayoutTests/inspector/css/nodeLayoutContextTypeChanged.html
@@ -65,6 +65,54 @@
         }
     });
 
+    addTestCase({
+        name: "CSS.nodeLayoutContextTypeChanged.FlexToNonFlex",
+        description: "Change a flex container to a non-flex container.",
+        selector: "#flexToNonFlex",
+        async domNodeHandler(domNode) {
+            InspectorTest.expectEqual(domNode.layoutContextType, WI.DOMNode.LayoutContextType.Flex, "Layout context should be `flex`.");
+
+            await Promise.all([
+                domNode.awaitEvent(WI.DOMNode.Event.LayoutContextTypeChanged),
+                changeElementDisplayValue("flexToNonFlex", "block"),
+            ]);
+
+            InspectorTest.expectEqual(domNode.layoutContextType, null, "Layout context should now be `null`.");
+        }
+    });
+
+    addTestCase({
+        name: "CSS.nodeLayoutContextTypeChanged.NonFlexToFlex",
+        description: "Change a non-flex container to a flex container.",
+        selector: "#nonFlexToFlex",
+        async domNodeHandler(domNode) {
+            InspectorTest.expectEqual(domNode.layoutContextType, null, "Layout context should be `null`.");
+
+            await Promise.all([
+                domNode.awaitEvent(WI.DOMNode.Event.LayoutContextTypeChanged),
+                changeElementDisplayValue("nonFlexToFlex", "flex"),
+            ]);
+
+            InspectorTest.expectEqual(domNode.layoutContextType, WI.DOMNode.LayoutContextType.Flex, "Layout context should now be `flex`.");
+        }
+    });
+
+    addTestCase({
+        name: "CSS.nodeLayoutContextTypeChanged.GridToFlex",
+        description: "Change a non-flex container to a flex container.",
+        selector: "#gridToFlex",
+        async domNodeHandler(domNode) {
+            InspectorTest.expectEqual(domNode.layoutContextType, WI.DOMNode.LayoutContextType.Grid, "Layout context should now be `grid`.");
+
+            await Promise.all([
+                domNode.awaitEvent(WI.DOMNode.Event.LayoutContextTypeChanged),
+                changeElementDisplayValue("gridToFlex", "flex"),
+            ]);
+
+            InspectorTest.expectEqual(domNode.layoutContextType, WI.DOMNode.LayoutContextType.Flex, "Layout context should now be `flex`.");
+        }
+    });
+
     WI.domManager.requestDocument().then((doc) => {
         documentNode = doc;
         suite.runTestCasesAndFinish();
@@ -75,6 +123,10 @@
     .grid-container {
         display: grid;
     }
+
+    .flex-container {
+        display: flex;
+    }
 </style>
 </head>
 <body onload="runTest()">
@@ -88,5 +140,20 @@
         <div></div>
         <div></div>
     </div>
+
+    <div id="flexToNonFlex" class="flex-container">
+        <div></div>
+        <div></div>
+    </div>
+
+    <div id="nonFlexToFlex">
+        <div></div>
+        <div></div>
+    </div>
+
+    <div id="gridToFlex" class="grid-container">
+        <div></div>
+        <div></div>
+    </div>
 </body>
 </html>
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 987441a..0fcb2e8 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,12 @@
+2022-01-24  Patrick Angle  <pangle@apple.com>
+
+        Web Inspector: [Flexbox] Add instrumentation/protocol bits for flex layout containers
+        https://bugs.webkit.org/show_bug.cgi?id=235454
+
+        Reviewed by Devin Rousso.
+
+        * inspector/protocol/CSS.json:
+
 2022-01-24  Mikhail R. Gadelha  <mikhail@igalia.com>
 
         [JSC][32bit] Fix regexp crash on ARMv7
diff --git a/Source/JavaScriptCore/inspector/protocol/CSS.json b/Source/JavaScriptCore/inspector/protocol/CSS.json
index 4aa786c..56568a7 100644
--- a/Source/JavaScriptCore/inspector/protocol/CSS.json
+++ b/Source/JavaScriptCore/inspector/protocol/CSS.json
@@ -257,7 +257,7 @@
         {
             "id": "LayoutContextType",
             "type": "string",
-            "enum": ["grid"],
+            "enum": ["flex", "grid"],
             "description": "The layout context type of a node."
         },
         {
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 87d1da3..c60715c 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,23 @@
+2022-01-24  Patrick Angle  <pangle@apple.com>
+
+        Web Inspector: [Flexbox] Add instrumentation/protocol bits for flex layout containers
+        https://bugs.webkit.org/show_bug.cgi?id=235454
+
+        Reviewed by Devin Rousso.
+
+        Added tests in inspector/css/nodeLayoutContextTypeChanged.html.
+
+        Add instrumentation to RenderFlexibleBox to observe elements becoming/ceasing to be flex containers. We only
+        instrument RenderFlexibleBox created with an Element, not a Document, since all anonymous nodes will have their
+        document passed, which means we would attempt to track multiple different nodes against the same document,
+        resulting in unexpected results. Conversely, we only instrument in the destructor for non-anonymous nodes.
+
+        * inspector/agents/InspectorCSSAgent.cpp:
+        (WebCore::InspectorCSSAgent::layoutContextTypeForRenderer):
+        * rendering/RenderFlexibleBox.cpp:
+        (WebCore::RenderFlexibleBox::RenderFlexibleBox):
+        (WebCore::RenderFlexibleBox::~RenderFlexibleBox):
+
 2022-01-24  Per Arne Vollan  <pvollan@apple.com>
 
         [iOS] Avoid calling IOSurfaceGetPropertyMaximum
diff --git a/Source/WebCore/inspector/agents/InspectorCSSAgent.cpp b/Source/WebCore/inspector/agents/InspectorCSSAgent.cpp
index 79a3245..d19ad3d 100644
--- a/Source/WebCore/inspector/agents/InspectorCSSAgent.cpp
+++ b/Source/WebCore/inspector/agents/InspectorCSSAgent.cpp
@@ -56,6 +56,7 @@
 #include "Node.h"
 #include "NodeList.h"
 #include "PseudoElement.h"
+#include "RenderFlexibleBox.h"
 #include "RenderGrid.h"
 #include "RenderStyleConstants.h"
 #include "SVGStyleElement.h"
@@ -938,6 +939,8 @@
 
 std::optional<Protocol::CSS::LayoutContextType> InspectorCSSAgent::layoutContextTypeForRenderer(RenderObject* renderer)
 {
+    if (is<RenderFlexibleBox>(renderer))
+        return Protocol::CSS::LayoutContextType::Flex;
     if (is<RenderGrid>(renderer))
         return Protocol::CSS::LayoutContextType::Grid;
     return std::nullopt;
diff --git a/Source/WebCore/rendering/RenderFlexibleBox.cpp b/Source/WebCore/rendering/RenderFlexibleBox.cpp
index f96dbec..a942f32 100644
--- a/Source/WebCore/rendering/RenderFlexibleBox.cpp
+++ b/Source/WebCore/rendering/RenderFlexibleBox.cpp
@@ -33,6 +33,7 @@
 
 #include "FlexibleBoxAlgorithm.h"
 #include "HitTestResult.h"
+#include "InspectorInstrumentation.h"
 #include "LayoutRepainter.h"
 #include "RenderChildIterator.h"
 #include "RenderLayer.h"
@@ -72,6 +73,8 @@
     : RenderBlock(element, WTFMove(style), 0)
 {
     setChildrenInline(false); // All of our children must be block-level.
+
+    InspectorInstrumentation::nodeLayoutContextChanged(element, this);
 }
 
 RenderFlexibleBox::RenderFlexibleBox(Document& document, RenderStyle&& style)
@@ -80,7 +83,11 @@
     setChildrenInline(false); // All of our children must be block-level.
 }
 
-RenderFlexibleBox::~RenderFlexibleBox() = default;
+RenderFlexibleBox::~RenderFlexibleBox()
+{
+    if (!isAnonymous())
+        InspectorInstrumentation::nodeLayoutContextChanged(nodeForNonAnonymous(), nullptr);
+}
 
 const char* RenderFlexibleBox::renderName() const
 {
diff --git a/Source/WebInspectorUI/ChangeLog b/Source/WebInspectorUI/ChangeLog
index 4c38ab5..b1a69a3 100644
--- a/Source/WebInspectorUI/ChangeLog
+++ b/Source/WebInspectorUI/ChangeLog
@@ -1,3 +1,12 @@
+2022-01-24  Patrick Angle  <pangle@apple.com>
+
+        Web Inspector: [Flexbox] Add instrumentation/protocol bits for flex layout containers
+        https://bugs.webkit.org/show_bug.cgi?id=235454
+
+        Reviewed by Devin Rousso.
+
+        * UserInterface/Models/DOMNode.js:
+
 2022-01-24  Devin Rousso  <drousso@apple.com>
 
         Web Inspector: Network: move filtering checkboxes into a single gear-with-contextmenu to save space
diff --git a/Source/WebInspectorUI/UserInterface/Models/DOMNode.js b/Source/WebInspectorUI/UserInterface/Models/DOMNode.js
index 02545cd..19fb022 100644
--- a/Source/WebInspectorUI/UserInterface/Models/DOMNode.js
+++ b/Source/WebInspectorUI/UserInterface/Models/DOMNode.js
@@ -1138,5 +1138,6 @@
 
 // Corresponds to `CSS.LayoutContextType`.
 WI.DOMNode.LayoutContextType = {
+    Flex: "flex",
     Grid: "grid",
 };