Title: [278607] trunk
Revision
278607
Author
[email protected]
Date
2021-06-08 08:57:00 -0700 (Tue, 08 Jun 2021)

Log Message

Web Inspector: Styles panel slow to render when inspecting node with many inherited CSS variables
https://bugs.webkit.org/show_bug.cgi?id=225972
<rdar://problem/78211185>

Reviewed by Devin Rousso.

Source/WebInspectorUI:

Do not show unused inherited CSS variables in the Styles details sidebar.

When aggregating styles for the selected node in `WI.DOMNodeStyles`, collect a list of names of CSS variables used in CSS property values.
In the Styles details sidebar, skip rendering declarations of inherited CSS variables that are not found in this list.

Always show inherited variables that are used, either directly inherited or via reference (variables using other variables in their value).
Always show inherited variables used as values of inheritable properties like color, font-size, etc.

When a CSS rule contains hidden inherited variables, offer a button to request disclosing them for that rule.
Option-click to show unused inherited variables in all matching rules.

Clicking the "Go to variable" button automatically renders all the unused variables in the CSS rule where the target variable is declared.

* Localizations/en.lproj/localizedStrings.js:
* UserInterface/Models/CSSProperty.js:
(WI.CSSProperty.findVariableNames):
* UserInterface/Models/DOMNodeStyles.js:
(WI.DOMNodeStyles):
(WI.DOMNodeStyles.prototype.get usedCSSVariables):
(WI.DOMNodeStyles.prototype._updateStyleCascade):
(WI.DOMNodeStyles.prototype._collectUsedCSSVariables):
* UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.css:
(.spreadsheet-style-declaration-editor .property):
(.spreadsheet-style-declaration-editor > .hidden-variables-button):
* UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.js:
(WI.SpreadsheetCSSStyleDeclarationEditor):
(WI.SpreadsheetCSSStyleDeclarationEditor.prototype.layout):
(WI.SpreadsheetCSSStyleDeclarationEditor.prototype.get propertiesToRender):
(WI.SpreadsheetCSSStyleDeclarationEditor.prototype.highlightProperty):
* UserInterface/Views/SpreadsheetCSSStyleDeclarationSection.js:
(WI.SpreadsheetCSSStyleDeclarationSection.prototype.set propertyVisibilityMode):
(WI.SpreadsheetCSSStyleDeclarationSection.prototype.spreadsheetCSSStyleDeclarationEditorSetAllPropertyVisibilityMode):
* UserInterface/Views/SpreadsheetRulesStyleDetailsPanel.js:
(WI.SpreadsheetRulesStyleDetailsPanel.prototype.spreadsheetCSSStyleDeclarationSectionSetAllPropertyVisibilityMode):

LayoutTests:

Add tests for logic to aggregate used CSS variables in Web Inspector.

* inspector/css/findVariableNames-expected.txt: Added.
* inspector/css/findVariableNames.html: Added.
* inspector/css/usedCSSVariables-expected.txt: Added.
* inspector/css/usedCSSVariables.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (278606 => 278607)


--- trunk/LayoutTests/ChangeLog	2021-06-08 14:16:21 UTC (rev 278606)
+++ trunk/LayoutTests/ChangeLog	2021-06-08 15:57:00 UTC (rev 278607)
@@ -1,3 +1,18 @@
+2021-06-08  Razvan Caliman  <[email protected]>
+
+        Web Inspector: Styles panel slow to render when inspecting node with many inherited CSS variables
+        https://bugs.webkit.org/show_bug.cgi?id=225972
+        <rdar://problem/78211185>
+
+        Reviewed by Devin Rousso.
+
+        Add tests for logic to aggregate used CSS variables in Web Inspector.
+
+        * inspector/css/findVariableNames-expected.txt: Added.
+        * inspector/css/findVariableNames.html: Added.
+        * inspector/css/usedCSSVariables-expected.txt: Added.
+        * inspector/css/usedCSSVariables.html: Added.
+
 2021-06-08  Alan Bujtas  <[email protected]>
 
         [LFC][TFC] Add initial percent value support for columns

Added: trunk/LayoutTests/inspector/css/findVariableNames-expected.txt (0 => 278607)


--- trunk/LayoutTests/inspector/css/findVariableNames-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/inspector/css/findVariableNames-expected.txt	2021-06-08 15:57:00 UTC (rev 278607)
@@ -0,0 +1,51 @@
+Test naive parsing of CSS variable names with CSSProperty.findVariableNames
+
+
+== Running test suite: CSSProperty.findVariableNames
+-- Running test case: CSSProperty.findVariableNames.Empty
+PASS: "" should contain these CSS variable names: [].
+
+-- Running test case: CSSProperty.findVariableNames.EmptyFunction
+PASS: "var()" should contain these CSS variable names: [].
+
+-- Running test case: CSSProperty.findVariableNames.EmptyNoFunction
+PASS: "--one" should contain these CSS variable names: [].
+
+-- Running test case: CSSProperty.findVariableNames.Basic
+PASS: "var(--one)" should contain these CSS variable names: ["--one"].
+
+-- Running test case: CSSProperty.findVariableNames.BasicWithFallback
+PASS: "var(--one, red)" should contain these CSS variable names: ["--one"].
+
+-- Running test case: CSSProperty.findVariableNames.BasicWithVariableFallback
+PASS: "var(--one, var(--two, red))" should contain these CSS variable names: ["--one","--two"].
+
+-- Running test case: CSSProperty.findVariableNames.Whitespace
+PASS: "var(    --one    )" should contain these CSS variable names: ["--one"].
+
+-- Running test case: CSSProperty.findVariableNames.Newline
+PASS: "var(
+--one
+)" should contain these CSS variable names: ["--one"].
+
+-- Running test case: CSSProperty.findVariableNames.Tab
+PASS: "var(	--one	)" should contain these CSS variable names: ["--one"].
+
+-- Running test case: CSSProperty.findVariableNames.Nested
+PASS: "var(--one, var(--two, var(--three)))" should contain these CSS variable names: ["--one","--two","--three"].
+
+-- Running test case: CSSProperty.findVariableNames.Content
+PASS: "content: "var(--one)"" should contain these CSS variable names: ["--one"].
+
+-- Running test case: CSSProperty.findVariableNames.Dashed
+PASS: "var(----o--n--e)" should contain these CSS variable names: ["----o--n--e"].
+
+-- Running test case: CSSProperty.findVariableNames.NaiveWhitespace
+PASS: "var(--one --two --three)" should contain these CSS variable names: ["--one"].
+
+-- Running test case: CSSProperty.findVariableNames.NaiveDataURI
+PASS: "data:text/plain;base64,xxxvar(--one)xxx" should contain these CSS variable names: ["--one"].
+
+-- Running test case: CSSProperty.findVariableNames.NaiveMalformed
+PASS: "var(--var(one))" should contain these CSS variable names: ["--var(one"].
+

Added: trunk/LayoutTests/inspector/css/findVariableNames.html (0 => 278607)


--- trunk/LayoutTests/inspector/css/findVariableNames.html	                        (rev 0)
+++ trunk/LayoutTests/inspector/css/findVariableNames.html	2021-06-08 15:57:00 UTC (rev 278607)
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script>
+
+function test()
+{
+    let suite = InspectorTest.createSyncSuite("CSSProperty.findVariableNames");
+
+    function addTestCase({name, _expression_, expected, checkUsedCSSVariableNames})
+    {
+        suite.addTestCase({
+            name,
+            test() {
+                let variables = WI.CSSProperty.findVariableNames(_expression_);
+                InspectorTest.expectShallowEqual(variables, expected, `"${_expression_}" should contain these CSS variable names: ${JSON.stringify(expected)}.`);
+            },
+        });
+    }
+
+    addTestCase({
+        name: "CSSProperty.findVariableNames.Empty",
+        _expression_: "",
+        expected: [],
+    });
+
+    addTestCase({
+        name: "CSSProperty.findVariableNames.EmptyFunction",
+        _expression_: "var()",
+        expected: [],
+    });
+
+    addTestCase({
+        name: "CSSProperty.findVariableNames.EmptyNoFunction",
+        _expression_: "--one",
+        expected: [],
+    });
+
+    addTestCase({
+        name: "CSSProperty.findVariableNames.Basic",
+        _expression_: "var(--one)",
+        expected: ["--one"],
+    });
+
+    addTestCase({
+        name: "CSSProperty.findVariableNames.BasicWithFallback",
+        _expression_: "var(--one, red)",
+        expected: ["--one"],
+    });
+
+    addTestCase({
+        name: "CSSProperty.findVariableNames.BasicWithVariableFallback",
+        _expression_: "var(--one, var(--two, red))",
+        expected: ["--one", "--two"],
+    });
+
+    addTestCase({
+        name: "CSSProperty.findVariableNames.Whitespace",
+        _expression_: "var(    --one    )",
+        expected: ["--one"],
+    });
+
+    addTestCase({
+        name: "CSSProperty.findVariableNames.Newline",
+        _expression_: "var(\n--one\n)",
+        expected: ["--one"],
+    });
+
+    addTestCase({
+        name: "CSSProperty.findVariableNames.Tab",
+        _expression_: "var(\t--one\t)",
+        expected: ["--one"],
+    });
+
+    addTestCase({
+        name: "CSSProperty.findVariableNames.Nested",
+        _expression_: "var(--one, var(--two, var(--three)))",
+        expected: ["--one", "--two", "--three"],
+    });
+
+    addTestCase({
+        name: "CSSProperty.findVariableNames.Content",
+        _expression_: "content: \"var(--one)\"",
+        expected: ["--one"],
+    });
+
+    addTestCase({
+        name: "CSSProperty.findVariableNames.Dashed",
+        _expression_: "var(----o--n--e)",
+        expected: ["----o--n--e"],
+    });
+
+    addTestCase({
+        name: "CSSProperty.findVariableNames.NaiveWhitespace",
+        _expression_: "var(--one --two --three)",
+        expected: ["--one"],
+    });
+
+    addTestCase({
+        name: "CSSProperty.findVariableNames.NaiveDataURI",
+        _expression_: "data:text/plain;base64,xxxvar(--one)xxx",
+        expected: ["--one"],
+    });
+
+    addTestCase({
+        name: "CSSProperty.findVariableNames.NaiveMalformed",
+        _expression_: "var(--var(one))",
+        expected: ["--var(one"],
+    });
+
+    suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body _onload_="runTest();">
+<p>Test naive parsing of CSS variable names with CSSProperty.findVariableNames</p>
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/inspector/css/usedCSSVariables-expected.txt (0 => 278607)


--- trunk/LayoutTests/inspector/css/usedCSSVariables-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/inspector/css/usedCSSVariables-expected.txt	2021-06-08 15:57:00 UTC (rev 278607)
@@ -0,0 +1,32 @@
+Test for DOMNodeStyles.usedCSSVariables
+
+
+== Running test suite: DOMNodeStyles.usedCSSVariables
+-- Running test case: DOMNodeStyles.usedCSSVariables.InheritedUsed
+PASS: Set should contain one used variable
+PASS: --inherited-color should be used
+
+-- Running test case: DOMNodeStyles.usedCSSVariables.InheritedUsedReferenced
+PASS: Set should contain two used variables
+PASS: --inherited-color should be used
+PASS: --color should be used
+
+-- Running test case: DOMNodeStyles.usedCSSVariables.InheritedNotUsed
+PASS: Set should contain one used variable
+PASS: --color should be used
+PASS: --inherited-color should not be used
+
+-- Running test case: DOMNodeStyles.usedCSSVariables.InheritedUsedFunction
+PASS: Set should contain one used variable
+PASS: --inherited-color should be used
+
+-- Running test case: DOMNodeStyles.usedCSSVariables.HighSpecificityUsed
+PASS: --color should be used
+
+-- Running test case: DOMNodeStyles.usedCSSVariables.InheritedHighSpecificityUsed
+PASS: Set should contain one used variable
+PASS: --color should be used
+
+-- Running test case: DOMNodeStyles.usedCSSVariables.InheritedHighSpecificityNotUsed
+PASS: --color should not be used
+

Added: trunk/LayoutTests/inspector/css/usedCSSVariables.html (0 => 278607)


--- trunk/LayoutTests/inspector/css/usedCSSVariables.html	                        (rev 0)
+++ trunk/LayoutTests/inspector/css/usedCSSVariables.html	2021-06-08 15:57:00 UTC (rev 278607)
@@ -0,0 +1,171 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script>
+
+function test()
+{
+    let suite = InspectorTest.createAsyncSuite("DOMNodeStyles.usedCSSVariables");
+
+    function addTestCase({name, description, selector, checkUsedCSSVariables})
+    {
+        suite.addTestCase({
+            name,
+            description,
+            async test() {
+                let documentNode = await WI.domManager.requestDocument();
+                let nodeId = await documentNode.querySelector(selector);
+                let domNode = await WI.domManager.nodeForId(nodeId);
+                InspectorTest.assert(domNode, `Should find DOM Node for selector '${selector}'.`);
+
+                let cssStyles = WI.cssManager.stylesForNode(domNode);
+                InspectorTest.assert(cssStyles, `Should find CSS Styles for DOM Node.`);
+
+                await cssStyles.refreshIfNeeded();
+
+                checkUsedCSSVariables(cssStyles.usedCSSVariables);
+            },
+        });
+    }
+
+    addTestCase({
+        name: "DOMNodeStyles.usedCSSVariables.InheritedUsed",
+        description: "A used inherited variable is found in the set of used variables",
+        selector: "#used-inherited-variable",
+        checkUsedCSSVariables(usedCSSVariables) {
+            InspectorTest.expectEqual(usedCSSVariables.size, 1, "Set should contain one used variable");
+            InspectorTest.expectTrue(usedCSSVariables.has("--inherited-color"), "--inherited-color should be used");
+        },
+    });
+
+    addTestCase({
+        name: "DOMNodeStyles.usedCSSVariables.InheritedUsedReferenced",
+        description: "An inherited variable referenced by another used variable is found in the set of used variables",
+        selector: "#used-referenced-inherited-variable",
+        checkUsedCSSVariables(usedCSSVariables) {
+            InspectorTest.expectEqual(usedCSSVariables.size, 2, "Set should contain two used variables");
+            InspectorTest.expectTrue(usedCSSVariables.has("--inherited-color"), "--inherited-color should be used");
+            InspectorTest.expectTrue(usedCSSVariables.has("--color"), "--color should be used");
+        },
+    });
+
+    addTestCase({
+        name: "DOMNodeStyles.usedCSSVariables.InheritedNotUsed",
+        description: "Unused inherited variables are not found in the set of used variables",
+        selector: "#unused-inherited-variable",
+        checkUsedCSSVariables(usedCSSVariables) {
+            InspectorTest.expectEqual(usedCSSVariables.size, 1, "Set should contain one used variable");
+            InspectorTest.expectTrue(usedCSSVariables.has("--color"), "--color should be used");
+            InspectorTest.expectFalse(usedCSSVariables.has("--inherited-color"), "--inherited-color should not be used");
+        },
+    });
+
+    addTestCase({
+        name: "DOMNodeStyles.usedCSSVariables.InheritedUsedFunction",
+        description: "An inherited variable used in a function value is found in the set of used variables",
+        selector: "#used-inherited-variable-function",
+        checkUsedCSSVariables(usedCSSVariables) {
+            InspectorTest.expectEqual(usedCSSVariables.size, 1, "Set should contain one used variable");
+            InspectorTest.expectTrue(usedCSSVariables.has("--inherited-color"), "--inherited-color should be used");
+        },
+    });
+
+    addTestCase({
+        name: "DOMNodeStyles.usedCSSVariables.HighSpecificityUsed",
+        description: "A variable declared in a higher specificity rule but used in a lower specificity rule is found in the set of used variables",
+        selector: "#used-higher-specificity",
+        checkUsedCSSVariables(usedCSSVariables) {
+            InspectorTest.expectTrue(usedCSSVariables.has("--color"), "--color should be used");
+        },
+    });
+
+    addTestCase({
+        name: "DOMNodeStyles.usedCSSVariables.InheritedHighSpecificityUsed",
+        description: "An inherited variable declared in a higher specificity rule but used in a lower specificity rule on an inheritable property (`color`) is found in the set of used variables",
+        selector: "#used-higher-specificity-inheritable > p",
+        checkUsedCSSVariables(usedCSSVariables) {
+            InspectorTest.expectEqual(usedCSSVariables.size, 1, "Set should contain one used variable");
+            InspectorTest.expectTrue(usedCSSVariables.has("--color"), "--color should be used");
+        },
+    });
+
+    addTestCase({
+        name: "DOMNodeStyles.usedCSSVariables.InheritedHighSpecificityNotUsed",
+        description: "An inherited variable declared in a higher specificity rule but used in a lower specificity rule on a non-inheritable property (`background-color`) is not found in the set of used variables",
+        selector: "#unused-higher-specificity-non-inheritable > p",
+        checkUsedCSSVariables(usedCSSVariables) {
+            InspectorTest.expectFalse(usedCSSVariables.has("--color"), "--color should not be used");
+        },
+    });
+
+    suite.runTestCasesAndFinish();
+}
+</script>
+<style>
+
+html {
+    --inherited-color: green;
+}
+
+div#used-inherited-variable {
+    color: var(--inherited-color, red);
+}
+
+div#used-referenced-inherited-variable {
+    --color: var(--inherited-color);
+    color: var(--color, red);
+}
+
+div#unused-inherited-variable {
+    --color: green;
+    color: var(--color, red);
+}
+
+div#used-inherited-variable-function {
+    background: linear-gradient(90deg, var(--inherited-color, red), white);
+}
+
+div.used-lower-specificity {
+    background-color: var(--color, red);
+}
+
+div#used-higher-specificity {
+    --color: green;
+}
+
+div.used-lower-specificity-inheritable {
+    color: var(--color, red);
+}
+
+div#used-higher-specificity-inheritable {
+    --color: green;
+}
+
+div.unused-lower-specificity-non-inheritable {
+    background-color: var(--color, red);
+}
+
+div#unused-higher-specificity-non-inheritable {
+    --color: green;
+}
+
+</style>
+</head>
+<body _onload_="runTest();">
+<p>Test for DOMNodeStyles.usedCSSVariables</p>
+<div>
+    <div id="used-inherited-variable"></div>
+    <div id="used-referenced-inherited-variable"></div>
+    <div id="unused-inherited-variable"></div>
+    <div id="used-inherited-variable-function"></div>
+    <div id="used-higher-specificity" class="used-lower-specificity"></div>
+    <div id="used-higher-specificity-inheritable" class="used-lower-specificity-inheritable">
+        <p></p>
+    </div>
+    <div id="unused-higher-specificity-non-inheritable" class="unused-lower-specificity-non-inheritable">
+        <p></p>
+    </div>
+</div>
+</body>
+</html>
\ No newline at end of file

Modified: trunk/Source/WebInspectorUI/ChangeLog (278606 => 278607)


--- trunk/Source/WebInspectorUI/ChangeLog	2021-06-08 14:16:21 UTC (rev 278606)
+++ trunk/Source/WebInspectorUI/ChangeLog	2021-06-08 15:57:00 UTC (rev 278607)
@@ -1,3 +1,46 @@
+2021-06-08  Razvan Caliman  <[email protected]>
+
+        Web Inspector: Styles panel slow to render when inspecting node with many inherited CSS variables
+        https://bugs.webkit.org/show_bug.cgi?id=225972
+        <rdar://problem/78211185>
+
+        Reviewed by Devin Rousso.
+
+        Do not show unused inherited CSS variables in the Styles details sidebar.
+
+        When aggregating styles for the selected node in `WI.DOMNodeStyles`, collect a list of names of CSS variables used in CSS property values.
+        In the Styles details sidebar, skip rendering declarations of inherited CSS variables that are not found in this list.
+
+        Always show inherited variables that are used, either directly inherited or via reference (variables using other variables in their value).
+        Always show inherited variables used as values of inheritable properties like color, font-size, etc.
+
+        When a CSS rule contains hidden inherited variables, offer a button to request disclosing them for that rule.
+        Option-click to show unused inherited variables in all matching rules.
+
+        Clicking the "Go to variable" button automatically renders all the unused variables in the CSS rule where the target variable is declared.
+
+        * Localizations/en.lproj/localizedStrings.js:
+        * UserInterface/Models/CSSProperty.js:
+        (WI.CSSProperty.findVariableNames):
+        * UserInterface/Models/DOMNodeStyles.js:
+        (WI.DOMNodeStyles):
+        (WI.DOMNodeStyles.prototype.get usedCSSVariables):
+        (WI.DOMNodeStyles.prototype._updateStyleCascade):
+        (WI.DOMNodeStyles.prototype._collectUsedCSSVariables):
+        * UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.css:
+        (.spreadsheet-style-declaration-editor .property):
+        (.spreadsheet-style-declaration-editor > .hidden-variables-button):
+        * UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.js:
+        (WI.SpreadsheetCSSStyleDeclarationEditor):
+        (WI.SpreadsheetCSSStyleDeclarationEditor.prototype.layout):
+        (WI.SpreadsheetCSSStyleDeclarationEditor.prototype.get propertiesToRender):
+        (WI.SpreadsheetCSSStyleDeclarationEditor.prototype.highlightProperty):
+        * UserInterface/Views/SpreadsheetCSSStyleDeclarationSection.js:
+        (WI.SpreadsheetCSSStyleDeclarationSection.prototype.set propertyVisibilityMode):
+        (WI.SpreadsheetCSSStyleDeclarationSection.prototype.spreadsheetCSSStyleDeclarationEditorSetAllPropertyVisibilityMode):
+        * UserInterface/Views/SpreadsheetRulesStyleDetailsPanel.js:
+        (WI.SpreadsheetRulesStyleDetailsPanel.prototype.spreadsheetCSSStyleDeclarationSectionSetAllPropertyVisibilityMode):
+
 2021-06-04  Devin Rousso  <[email protected]>
 
         Web Inspector: cannot see experimental settings when inspecting `ServiceWorker`

Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (278606 => 278607)


--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js	2021-06-08 14:16:21 UTC (rev 278606)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js	2021-06-08 15:57:00 UTC (rev 278607)
@@ -1028,6 +1028,8 @@
 /* Context menu item for opening the target item in a new window. */
 localizedStrings["Open in New Window @ Context Menu Item"] = "Open in New Window";
 localizedStrings["Option-click to show source"] = "Option-click to show source";
+/* Tooltip with instructions on how to show all hidden CSS variables */
+localizedStrings["Option-click to show unused CSS variables from all rules @ Styles Sidebar Panel Tooltip"] = "Option-click to show unused CSS variables from all rules";
 localizedStrings["Options"] = "Options";
 /* Property value for `font-variant-numeric: ordinal`. */
 localizedStrings["Ordinal Letter Forms @ Font Details Sidebar Property Value"] = "Ordinal Letter Forms";
@@ -1319,6 +1321,10 @@
 localizedStrings["Shared Focus"] = "Shared Focus";
 localizedStrings["Shortest property path to %s"] = "Shortest property path to %s";
 localizedStrings["Show %d More"] = "Show %d More";
+/* Text label for button to reveal multiple unused CSS variables */
+localizedStrings["Show %d unused CSS variable (singular) @ Styles Sidebar Panel"] = "Show %d unused CSS variable";
+/* Text label for button to reveal one unused CSS variable */
+localizedStrings["Show %d unused CSS variables (plural) @ Styles Sidebar Panel"] = "Show %d unused CSS variables";
 localizedStrings["Show All"] = "Show All";
 localizedStrings["Show All (%d More)"] = "Show All (%d More)";
 localizedStrings["Show All Nodes (%d More)"] = "Show All Nodes (%d More)";

Modified: trunk/Source/WebInspectorUI/UserInterface/Models/CSSProperty.js (278606 => 278607)


--- trunk/Source/WebInspectorUI/UserInterface/Models/CSSProperty.js	2021-06-08 14:16:21 UTC (rev 278606)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/CSSProperty.js	2021-06-08 15:57:00 UTC (rev 278607)
@@ -49,6 +49,39 @@
         return name.startsWith("--");
     }
 
+    // FIXME: <https://webkit.org/b/226647> This naively collects variable-like names used in values. It should be hardened.
+    static findVariableNames(string)
+    {
+        const prefix = "var(--";
+        let prefixCursor = 0;
+        let cursor = 0;
+        let nameStartIndex = 0;
+        let names = [];
+
+        function isTerminatingChar(char) {
+            return char === ")" || char === "," || char === " " || char === "\n" || char === "\t";
+        }
+
+        while (cursor < string.length) {
+            if (nameStartIndex && isTerminatingChar(string.charAt(cursor))) {
+                names.push("--" + string.substring(nameStartIndex, cursor));
+                nameStartIndex = 0;
+            }
+
+            if (prefixCursor === prefix.length) {
+                prefixCursor = 0;
+                nameStartIndex = cursor;
+            }
+
+            if (string.charAt(cursor) === prefix.charAt(prefixCursor))
+                prefixCursor++;
+
+            cursor++;
+        }
+
+        return names;
+    }
+
     // Public
 
     get ownerStyle()

Modified: trunk/Source/WebInspectorUI/UserInterface/Models/DOMNodeStyles.js (278606 => 278607)


--- trunk/Source/WebInspectorUI/UserInterface/Models/DOMNodeStyles.js	2021-06-08 14:16:21 UTC (rev 278606)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/DOMNodeStyles.js	2021-06-08 15:57:00 UTC (rev 278607)
@@ -46,6 +46,7 @@
         this._computedPrimaryFont = null;
 
         this._propertyNameToEffectivePropertyMap = {};
+        this._usedCSSVariables = new Set;
 
         this._pendingRefreshTask = null;
         this.refresh();
@@ -129,6 +130,7 @@
     get computedStyle() { return this._computedStyle; }
     get orderedStyles() { return this._orderedStyles; }
     get computedPrimaryFont() { return this._computedPrimaryFont; }
+    get usedCSSVariables() { return this._usedCSSVariables; }
 
     get needsRefresh()
     {
@@ -767,6 +769,7 @@
 
         this._associateRelatedProperties(cascadeOrderedStyleDeclarations, this._propertyNameToEffectivePropertyMap);
         this._markOverriddenProperties(cascadeOrderedStyleDeclarations, this._propertyNameToEffectivePropertyMap);
+        this._collectUsedCSSVariables(cascadeOrderedStyleDeclarations);
 
         for (let pseudoElementInfo of this._pseudoElements.values()) {
             pseudoElementInfo.orderedStyles = this._collectStylesInCascadeOrder(pseudoElementInfo.matchedRules, null, null);
@@ -942,6 +945,35 @@
         }
     }
 
+    _collectUsedCSSVariables(styles)
+    {
+        this._usedCSSVariables = new Set;
+
+        for (let style of styles) {
+            for (let property of style.enabledProperties) {
+                let variables = WI.CSSProperty.findVariableNames(property.value);
+
+                if (!style.inherited) {
+                    // FIXME: <https://webkit.org/b/226648> Support the case of variables declared on matching styles but not used anywhere.
+                    this._usedCSSVariables.addAll(variables);
+                    continue;
+                }
+
+                // Always collect variables used in values of inheritable properties.
+                if (WI.CSSKeywordCompletions.InheritedProperties.has(property.name)) {
+                    this._usedCSSVariables.addAll(variables);
+                    continue;
+                }
+
+                // For variables from inherited styles, leverage the fact that styles are already sorted in cascade order to support inherited variables referencing other variables.
+                // If the variable was found to be used before, collect any variables used in its declaration value
+                // (if any variables are found, this isn't the end of the variable reference chain in the inheritance stack).
+                if (property.isVariable && this._usedCSSVariables.has(property.name))
+                    this._usedCSSVariables.addAll(variables);
+            }
+        }
+    }
+
     _isPropertyFoundInMatchingRules(propertyName)
     {
         return this._orderedStyles.some((style) => {

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.css (278606 => 278607)


--- trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.css	2021-06-08 14:16:21 UTC (rev 278606)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.css	2021-06-08 15:57:00 UTC (rev 278607)
@@ -33,6 +33,8 @@
 
     --background-color-selected: var(--selected-text-background-color);
     --border-color-selected: var(--selected-background-color);
+    --property-checkbox-width: 17px;
+    --property-indentation: calc(var(--css-declaration-horizontal-padding) + var(--property-checkbox-width));
 }
 
 .spreadsheet-style-declaration-editor:empty {
@@ -41,7 +43,7 @@
 
 .spreadsheet-style-declaration-editor .property {
     padding-right: var(--css-declaration-horizontal-padding);
-    padding-left: calc(var(--css-declaration-horizontal-padding) + 17px);
+    padding-left: var(--property-indentation);
     border-right: 2px solid transparent;
     border-left: 1px solid transparent;
     outline: none;
@@ -233,6 +235,10 @@
     white-space: nowrap;
 }
 
+.spreadsheet-style-declaration-editor > .hidden-variables-button {
+    margin-left: var(--property-indentation);
+}
+
 body.meta-key-pressed .spreadsheet-css-declaration:not(.locked) > .spreadsheet-style-declaration-editor > .property > .content :matches(.name, .value):not(.editing):hover {
     color: var(--syntax-highlight-link-color) !important;
     text-decoration: underline !important;

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.js (278606 => 278607)


--- trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.js	2021-06-08 14:16:21 UTC (rev 278606)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.js	2021-06-08 15:57:00 UTC (rev 278607)
@@ -40,7 +40,8 @@
 
         this._showsImplicitProperties = false;
         this._alwaysShowPropertyNames = new Set;
-        this._propertyVisibilityMode = WI.SpreadsheetCSSStyleDeclarationEditor.PropertyVisibilityMode.ShowAll;
+        this._propertyVisibilityMode = WI.SpreadsheetCSSStyleDeclarationEditor.PropertyVisibilityMode.HideUnusedInheritedVariables;
+        this._hiddenUnusedVariables = new Set;
         this._hideFilterNonMatchingProperties = false;
         this._sortPropertiesByName = false;
 
@@ -104,6 +105,26 @@
                 propertyViewPendingStartEditing = propertyView;
         }
 
+        if (this._hiddenUnusedVariables.size) {
+            let showHiddenVariablesButtonElement = this.element.appendChild(document.createElement("button"));
+            showHiddenVariablesButtonElement.classList.add("hidden-variables-button");
+            showHiddenVariablesButtonElement.title = WI.UIString("Option-click to show unused CSS variables from all rules", "Option-click to show unused CSS variables from all rules @ Styles Sidebar Panel Tooltip", "Tooltip with instructions on how to show all hidden CSS variables");
+
+            const labelSingular = WI.UIString("Show %d unused CSS variable", "Show %d unused CSS variable (singular) @ Styles Sidebar Panel", "Text label for button to reveal one unused CSS variable");
+            const labelPlural = WI.UIString("Show %d unused CSS variables", "Show %d unused CSS variables (plural) @ Styles Sidebar Panel", "Text label for button to reveal multiple unused CSS variables");
+            let label = this._hiddenUnusedVariables.size > 1 ? labelPlural : labelSingular;
+
+            showHiddenVariablesButtonElement.textContent = label.format(this._hiddenUnusedVariables.size);
+            showHiddenVariablesButtonElement.addEventListener("click", (event) => {
+                if (event.altKey) {
+                    this._setAllPropertyVisibilityMode(WI.SpreadsheetCSSStyleDeclarationEditor.PropertyVisibilityMode.ShowAll);
+                    return;
+                }
+
+                this.propertyVisibilityMode = WI.SpreadsheetCSSStyleDeclarationEditor.PropertyVisibilityMode.ShowAll;
+            });
+        }
+
         if (propertyViewPendingStartEditing) {
             propertyViewPendingStartEditing.startEditingName();
             this._propertyPendingStartEditing = null;
@@ -117,6 +138,11 @@
         else if (this.hasSelectedProperties())
             this.selectProperties(this._anchorIndex, this._focusIndex);
 
+        if (this._pendingPropertyToHighlight) {
+            this.highlightProperty(this._pendingPropertyToHighlight);
+            this._pendingPropertyToHighlight = null;
+        }
+
         this._updateDebugLockStatus();
     }
 
@@ -234,7 +260,10 @@
 
         let hideVariables = this._propertyVisibilityMode === SpreadsheetCSSStyleDeclarationEditor.PropertyVisibilityMode.HideVariables;
         let hideNonVariables = this._propertyVisibilityMode === SpreadsheetCSSStyleDeclarationEditor.PropertyVisibilityMode.HideNonVariables;
+        let hideUnusedInheritedVariables = this._propertyVisibilityMode === SpreadsheetCSSStyleDeclarationEditor.PropertyVisibilityMode.HideUnusedInheritedVariables;
 
+        this._hiddenUnusedVariables = new Set;
+
         return properties.filter((property) => {
             if (!property.isVariable && hideNonVariables)
                 return false;
@@ -242,6 +271,11 @@
             if (property.isVariable && hideVariables)
                 return false;
 
+            if (property.isVariable && hideUnusedInheritedVariables && this._style.inherited && !this._style.nodeStyles.usedCSSVariables.has(property.name)) {
+                this._hiddenUnusedVariables.add(property);
+                return false;
+            }
+
             return !property.implicit || this._showsImplicitProperties || this._alwaysShowPropertyNames.has(property.canonicalName);
         });
     }
@@ -277,6 +311,12 @@
 
     highlightProperty(property)
     {
+        if (!property.overridden && this._hiddenUnusedVariables.has(property)) {
+            this._pendingPropertyToHighlight = property;
+            this.propertyVisibilityMode = WI.SpreadsheetCSSStyleDeclarationEditor.PropertyVisibilityMode.ShowAll;
+            return true;
+        }
+
         let propertiesMatch = (cssProperty) => {
             if (cssProperty.attached && !cssProperty.overridden) {
                 if (cssProperty.canonicalName === property.canonicalName || hasMatchingLonghandProperty(cssProperty))
@@ -683,6 +723,11 @@
 
         this.element.classList.toggle("debug-style-locked", this._style.locked);
     }
+
+    _setAllPropertyVisibilityMode(propertyVisibilityMode)
+    {
+        this._delegate?.spreadsheetCSSStyleDeclarationEditorSetAllPropertyVisibilityMode?.(this, propertyVisibilityMode);
+    }
 };
 
 WI.SpreadsheetCSSStyleDeclarationEditor.Event = {
@@ -695,4 +740,5 @@
     ShowAll: Symbol("variable-visibility-show-all"),
     HideVariables: Symbol("variable-visibility-hide-variables"),
     HideNonVariables: Symbol("variable-visibility-hide-non-variables"),
+    HideUnusedInheritedVariables: Symbol("variable-visibility-hide-unused-inherited-variables"),
 };

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationSection.js (278606 => 278607)


--- trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationSection.js	2021-06-08 14:16:21 UTC (rev 278606)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationSection.js	2021-06-08 15:57:00 UTC (rev 278607)
@@ -58,6 +58,11 @@
         return this._style.editable;
     }
 
+    set propertyVisibilityMode(propertyVisibilityMode)
+    {
+        this._propertiesEditor.propertyVisibilityMode = propertyVisibilityMode;
+    }
+
     initialLayout()
     {
         super.initialLayout();
@@ -284,6 +289,11 @@
             this._delegate.spreadsheetCSSStyleDeclarationSectionSelectProperty(property);
     }
 
+    spreadsheetCSSStyleDeclarationEditorSetAllPropertyVisibilityMode(editor, propertyVisibilityMode)
+    {
+        this._delegate?.spreadsheetCSSStyleDeclarationSectionSetAllPropertyVisibilityMode?.(this, propertyVisibilityMode);
+    }
+
     applyFilter(filterText)
     {
         this._filterText = filterText;

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetRulesStyleDetailsPanel.js (278606 => 278607)


--- trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetRulesStyleDetailsPanel.js	2021-06-08 14:16:21 UTC (rev 278606)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetRulesStyleDetailsPanel.js	2021-06-08 15:57:00 UTC (rev 278607)
@@ -203,6 +203,12 @@
         this.nodeStyles.addRule(this._newRuleSelector, text);
     }
 
+    spreadsheetCSSStyleDeclarationSectionSetAllPropertyVisibilityMode(section, propertyVisibilityMode)
+    {
+        for (let section of this._sections)
+            section.propertyVisibilityMode = propertyVisibilityMode;
+    }
+
     // Protected
 
     layout()
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to