Changeset 227370 in webkit
- Timestamp:
- Jan 22, 2018 4:52:32 PM (6 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r227369 r227370 1 2018-01-22 Nikita Vasilyev <nvasilyev@apple.com> 2 3 Web Inspector: Styles Redesign: data corruption when updating values quickly 4 https://bugs.webkit.org/show_bug.cgi?id=179461 5 <rdar://problem/35431882> 6 7 Reviewed by Joseph Pecoraro. 8 9 * inspector/css/modify-css-property-expected.txt: Added. 10 * inspector/css/modify-css-property.html: Added. 11 1 12 2018-01-22 Matt Lewis <jlewis3@apple.com> 2 13 -
trunk/Source/WebInspectorUI/ChangeLog
r227244 r227370 1 2018-01-22 Nikita Vasilyev <nvasilyev@apple.com> 2 3 Web Inspector: Styles Redesign: data corruption when updating values quickly 4 https://bugs.webkit.org/show_bug.cgi?id=179461 5 <rdar://problem/35431882> 6 7 Reviewed by Joseph Pecoraro. 8 9 Data corruption used to happen because CSSStyleDeclaration.prototype.text didn't 10 update synchronously. Making two or more quick changes resulted in corrupted data. 11 12 Imagine we modify a CSS value 3 times: 13 14 Front-end: (1)-(2)---(3) 15 Back-end: (1)-----(2)-(3) 16 17 The first response from the backend could happen after the 2nd edit. In this patch, 18 CSSStyleDeclaration is locked when its view is being edited. 19 20 To correctly display invalid and overridden properties, the backend is allowed to update 21 CSSStyleDeclaration and CSSProperty when they're locked if the text from the backend 22 matches the model's text. This should happen when the backend is caught up with the 23 front-end changes. 24 25 * UserInterface/Models/CSSProperty.js: 26 (WI.CSSProperty.prototype.update): 27 * UserInterface/Models/CSSStyleDeclaration.js: 28 (WI.CSSStyleDeclaration): 29 (WI.CSSStyleDeclaration.prototype.get locked): 30 (WI.CSSStyleDeclaration.prototype.set locked): 31 (WI.CSSStyleDeclaration.prototype.set text): 32 33 * UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.js: 34 (WI.SpreadsheetCSSStyleDeclarationEditor): 35 (WI.SpreadsheetCSSStyleDeclarationEditor.prototype.initialLayout): 36 (WI.SpreadsheetCSSStyleDeclarationEditor.prototype.detached): 37 (WI.SpreadsheetCSSStyleDeclarationEditor.prototype.get editing): 38 (WI.SpreadsheetCSSStyleDeclarationEditor.prototype.set focused): 39 (WI.SpreadsheetCSSStyleDeclarationEditor.prototype.set inlineSwatchActive): 40 (WI.SpreadsheetCSSStyleDeclarationEditor.prototype.stylePropertyInlineSwatchActivated): 41 (WI.SpreadsheetCSSStyleDeclarationEditor.prototype.stylePropertyInlineSwatchDeactivated): 42 (WI.SpreadsheetCSSStyleDeclarationEditor.prototype._propertiesChanged): 43 (WI.SpreadsheetCSSStyleDeclarationEditor.prototype._updateStyleLock): 44 Lock CSSStyleDeclaration when a CSS property name or value is focused or 45 an inline widget is active. 46 47 * UserInterface/Views/SpreadsheetCSSStyleDeclarationSection.js: 48 (WI.SpreadsheetCSSStyleDeclarationSection): 49 (WI.SpreadsheetCSSStyleDeclarationSection.prototype._handleMouseDown): 50 (WI.SpreadsheetCSSStyleDeclarationSection.prototype._handleClick): 51 * UserInterface/Views/SpreadsheetStyleProperty.js: 52 (WI.SpreadsheetStyleProperty): 53 (WI.SpreadsheetStyleProperty.prototype._createInlineSwatch): 54 When selector is focused, clicking on the white-space should not add a new blank property. 55 1 56 2018-01-19 Ross Kirsling <ross.kirsling@sony.com> 2 57 -
trunk/Source/WebInspectorUI/UserInterface/Models/CSSProperty.js
r225299 r227370 71 71 update(text, name, value, priority, enabled, overridden, implicit, anonymous, valid, styleSheetTextRange, dontFireEvents) 72 72 { 73 // Locked CSSProperty can still be updated from the back-end when the text matches. 74 // We need to do this to keep attributes such as valid and overridden up to date. 75 if (this._ownerStyle && this._ownerStyle.locked && text !== this._text) 76 return; 77 73 78 text = text || ""; 74 79 name = name || ""; -
trunk/Source/WebInspectorUI/UserInterface/Models/CSSStyleDeclaration.js
r225568 r227370 41 41 this._inherited = inherited || false; 42 42 43 this._locked = false; 43 44 this._pendingProperties = []; 44 45 this._propertyNameMap = {}; … … 50 51 this._allVisibleProperties = null; 51 52 52 this.update(text, properties, styleSheetTextRange, true);53 this.update(text, properties, styleSheetTextRange, {dontFireEvents: true}); 53 54 } 54 55 … … 99 100 } 100 101 101 update(text, properties, styleSheetTextRange, dontFireEvents) 102 { 102 get locked() { return this._locked; } 103 set locked(value) { this._locked = value; } 104 105 update(text, properties, styleSheetTextRange, options = {}) 106 { 107 let dontFireEvents = options.dontFireEvents || false; 108 let suppressLock = options.suppressLock || false; 109 110 if (this._locked && !suppressLock && text !== this._text) 111 return; 112 103 113 text = text || ""; 104 114 properties = properties || []; … … 162 172 // Don't fire the event if there is text and it hasn't changed. 163 173 if (oldText && this._text && oldText === this._text) { 164 // We shouldn't have any added or removed properties in this case. 165 console.assert(!addedProperties.length && !removedProperties.length); 174 if (!this._locked || suppressLock) { 175 // We shouldn't have any added or removed properties in this case. 176 console.assert(!addedProperties.length && !removedProperties.length); 177 } 178 166 179 if (!addedProperties.length && !removedProperties.length) 167 180 return; … … 209 222 this.dispatchEventToListeners(WI.CSSStyleDeclaration.Event.InitialTextModified); 210 223 } 224 225 // Update text immediately when it was modified via the styles sidebar. 226 if (this._locked) 227 this._text = text; 211 228 212 229 this._nodeStyles.changeStyleText(this, text); … … 371 388 this._allProperties[index].index = index; 372 389 373 const suppressEvents = true; 374 this.update(this._text, this._allProperties, this._styleSheetTextRange, suppressEvents); 390 this.update(this._text, this._allProperties, this._styleSheetTextRange, {dontFireEvents: true, suppressLock: true}); 375 391 376 392 return property; -
trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationEditor.js
r227232 r227370 35 35 this.style = style; 36 36 this._propertyViews = []; 37 38 this._inlineSwatchActive = false; 39 this._focused = false; 40 37 41 this._propertyPendingStartEditing = null; 38 42 this._filterText = null; … … 40 44 41 45 // Public 46 47 initialLayout() 48 { 49 if (!this.style.editable) 50 return; 51 52 this.element.addEventListener("focus", () => { this.focused = true; }, true); 53 this.element.addEventListener("blur", (event) => { 54 let focusedElement = event.relatedTarget; 55 if (focusedElement && focusedElement.isDescendant(this.element)) 56 return; 57 58 this.focused = false; 59 }, true); 60 } 42 61 43 62 layout() … … 75 94 detached() 76 95 { 96 this._inlineSwatchActive = false; 97 this.focused = false; 98 77 99 for (let propertyView of this._propertyViews) 78 100 propertyView.detached(); … … 98 120 99 121 this.needsLayout(); 122 } 123 124 get editing() 125 { 126 return this._focused || this._inlineSwatchActive; 127 } 128 129 set focused(value) 130 { 131 this._focused = value; 132 this._updateStyleLock(); 133 } 134 135 set inlineSwatchActive(value) 136 { 137 this._inlineSwatchActive = value; 138 this._updateStyleLock(); 100 139 } 101 140 … … 161 200 162 201 return false; 163 }164 165 isFocused()166 {167 let focusedElement = document.activeElement;168 169 if (!focusedElement || focusedElement.tagName === "BODY")170 return false;171 172 return focusedElement.isSelfOrDescendant(this.element);173 202 } 174 203 … … 223 252 } 224 253 254 // SpreadsheetStyleProperty delegate 255 225 256 spreadsheetStylePropertyRemoved(propertyView) 226 257 { 227 258 this._propertyViews.remove(propertyView); 228 259 this.updateLayout(); 260 } 261 262 stylePropertyInlineSwatchActivated() 263 { 264 this.inlineSwatchActive = true; 265 } 266 267 stylePropertyInlineSwatchDeactivated() 268 { 269 this.inlineSwatchActive = false; 229 270 } 230 271 … … 279 320 _propertiesChanged(event) 280 321 { 281 if (this. isFocused()) {322 if (this.editing) { 282 323 for (let propertyView of this._propertyViews) 283 324 propertyView.updateStatus(); … … 285 326 this.needsLayout(); 286 327 } 328 329 _updateStyleLock() 330 { 331 this.style.locked = this._focused || this._inlineSwatchActive; 332 } 287 333 }; 288 334 -
trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetCSSStyleDeclarationSection.js
r226082 r227370 41 41 this._filterText = null; 42 42 this._shouldFocusSelectorElement = false; 43 this._was Focused= false;43 this._wasEditing = false; 44 44 } 45 45 … … 47 47 48 48 get style() { return this._style; } 49 50 get propertiesEditor() { return this._propertiesEditor; }51 49 52 50 get editable() … … 153 151 } 154 152 153 // SpreadsheetSelectorField delegate 154 155 155 spreadsheetSelectorFieldDidChange(direction) 156 156 { … … 181 181 this._discardSelectorChange(); 182 182 } 183 184 // SpreadsheetCSSStyleDeclarationEditor delegate 183 185 184 186 cssStyleDeclarationEditorStartEditingAdjacentRule(toPreviousRule) … … 419 421 _handleMouseDown(event) 420 422 { 421 this._was Focused = this._propertiesEditor.isFocused();423 this._wasEditing = this._propertiesEditor.editing || document.activeElement === this._selectorElement; 422 424 } 423 425 424 426 _handleClick(event) 425 427 { 426 if (this._was Focused)428 if (this._wasEditing) 427 429 return; 428 430 -
trunk/Source/WebInspectorUI/UserInterface/Views/SpreadsheetStyleProperty.js
r227232 r227370 356 356 }, this); 357 357 358 if (typeof this._delegate.stylePropertyInlineSwatchActivated === "function") { 359 swatch.addEventListener(WI.InlineSwatch.Event.Activated, () => { 360 this._delegate.stylePropertyInlineSwatchActivated(); 361 }); 362 } 363 364 if (typeof this._delegate.stylePropertyInlineSwatchDeactivated === "function") { 365 swatch.addEventListener(WI.InlineSwatch.Event.Deactivated, () => { 366 this._delegate.stylePropertyInlineSwatchDeactivated(); 367 }); 368 } 369 358 370 tokenElement.append(swatch.element, innerElement); 359 371
Note: See TracChangeset
for help on using the changeset viewer.