[webkit-changes] [WebKit/WebKit] 84150e: Web Inspector: New CSS property unexpectedly dropp...
Razvan Caliman - Apple
noreply at github.com
Mon Mar 20 00:36:56 PDT 2023
Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: 84150ea85574551811c8802fe27fa252bc571d31
https://github.com/WebKit/WebKit/commit/84150ea85574551811c8802fe27fa252bc571d31
Author: Razvan Caliman <rcaliman at apple.com>
Date: 2023-03-20 (Mon, 20 Mar 2023)
Changed paths:
M Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationSection.js
M Source/WebInspectorUI/UserInterface/Views/SpreadsheetRuleHeaderField.js
Log Message:
-----------
Web Inspector: New CSS property unexpectedly dropped from empty CSS rule when tabbing through or editing selector
https://bugs.webkit.org/show_bug.cgi?id=245768
Reviewed by Patrick Angle.
There are two issues here:
1) changing the selector of an empty CSS rule causes the first added CSS property to be dropped.
2) tabbing through the editable text field for a CSS selector marks it as changed even when it's not.
The core problem is the order of operations.
Tabbing out of a CSS selector text field first calls
`SpreadsheetCSSStyleDeclarationSection.spreadsheetRuleHeaderFieldWillNavigate()`
from the `SpreadsheetRuleHeaderField._handleKeyDown` handler.
For an empty CSS rule, this creates a new blank CSS property with:
`SpreadsheetCSSStyleDeclarationEditor.startEditingFirstProperty()` -> `CSSStyleDeclaration.newBlankProperty()`.
At this point, the frontend model for the CSS rule contains a `CSSStyleDeclaration` with one `CSSProperty`.
In quick succession, the second operation happens when the selector text field loses focus:
`SpreadsheetCSSStyleDeclarationSection.spreadsheetRuleHeaderFieldDidCommit()`
from the `SpreadsheetRuleHeaderField._handleBlur` handler.
If the selector text has changed, a request is sent to the backend via `DOMNodeStyles.changeRuleSelector()`.
A request is then made for the latest matching styles via `DOMNodeStyles.refresh()`.
For an empty CSS rule, there are no matching styles. As a result, the `CSSStyleDeclaration` of the corresponding
CSS rule is updated with an empty list of CSS properties in `DOMNodeStyles._parseStyleDeclarationPayload()`:
```
if (style) {
style.update(text, properties, styleSheetTextRange);
return style;
}
```
This has the effect of orphaning the new blank `CSSProperty` introduced earlier.
`CSSProperty._updateOwnerStyleText()` is called to persist the `CSSProperty` to the backend.
This calls `CSSStyleDeclaration.generateFormattedText()` to serialize the whole CSS declaration block.
But our `CSSStyleDeclaration` was just emptied of properties by the update in
`DOMNodeStyles._parseStyleDeclarationPayload()` so it falls back to returning an empty string:
```
let styleText = "";
...
let properties = this._styleSheetTextRange ? this.visibleProperties : this._properties;
...
return styleText;
```
When the `CSSProperty` commits with an empty name and value, the matching styles obtained
in response to `DOMNodeStyles.refresh()` are empty, and the orphaned property is dropped.
Trying again with the newly created blank CSS property will work because this time
there's no race with `DOMNodeStyles.refresh()` from the selector change.
To fix the first issue, we must ensure that the operation to update the selector
and the style refresh it causes occurs before adding a new CSS property to avoid
the style refresh invalidating the models on the frontend.
To fix the second issue, we don't call `SpreadsheetRuleHeaderField.stopEditing()` in the
keydown handler for Tab or Enter because that resets `_valueBeforeEditing` which causes
the check in `SpreadsheetRuleHeaderField._handleBlur` to always consider the selector
as having been changed, thus triggering the operations described above.
* Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationSection.js:
(WI.SpreadsheetCSSStyleDeclarationSection):
(WI.SpreadsheetCSSStyleDeclarationSection.prototype._handleSpreadsheetSelectorFieldDidCommit):
(WI.SpreadsheetCSSStyleDeclarationSection.prototype._handleSpreadsheetSelectorFieldWillNavigate):
* Source/WebInspectorUI/UserInterface/Views/SpreadsheetRuleHeaderField.js:
(WI.SpreadsheetRuleHeaderField):
(WI.SpreadsheetRuleHeaderField.prototype.stopEditing):
(WI.SpreadsheetRuleHeaderField.prototype._handleBlur):
(WI.SpreadsheetRuleHeaderField.prototype._handleKeyDown):
Canonical link: https://commits.webkit.org/261861@main
More information about the webkit-changes
mailing list