Bug 1557689 Comment 2 Edit History

Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.

## Take this CSS

```css
.end {
  justify-content: end;
}

div {
  display: flex;
}
```

## This is what happens:

### Summary

#### We immediately update the UI

1. The checkbox next to `display:flex` is clicked, disabling the property.
2. We update the editor (crossing out and re-evaluating isUsed for `display:flex`).
3. The client emits `property-value-updated`.
4. The server emits `track-change` along with the changes.
5. The `track-change` data is stored.
6. Changes are queued for the `div` rule along with `display:flex`.

#### We apply the changes to the stylesheets

1. stylesheets::update() is called to update the style sheet in place with new text.
2. A `style-applied` event is triggered causing the `styles::_styleApplied()` method to reset `cssLogic`.
3. The `style-applied` event is triggered.
4. `styles::_onStyleApplied()` is called for the `div` rule.
5. `styles::_onStyleApplied()` is called for the `.end` rule.
6. `stylesheets::update()` sends a `media-rules-changed` event.
7. The rule URL is updated.
8. A `media-rules-changed` (I don't think this affects the rule view).
9. [styles::form] is triggered recalculating `isUsed` for `div`.
10. `onRuleUpdated()` is called.
11. We call `element-style::updateDeclarations()`.
12. We try to update the property state but WRONGLY believe that `justify-content::used = true` because the style change has not yet been applied to the content.

#### We respond to the reflows

1. At this point we realize that something changed in the rule view.
2. The reflow actor also notices these changes and sends a `reflows` event.
3. The `reflows` actor tells us which node has changed.
4. A second `reflows` event.
5. The second `reflows` actor tells us which node has changed.
6. CSSLogic now rebuilds its list of rules for all stylesheets.
7. `styles::form()` is called updating `isUsed` for `justify:content` AND GETTING THE CORRECT RESULT THIS TIME.
8. `styles::form()` is called updating `isUsed` for `display:flex`).

#### The problem

1. WE SHOULD UPDATE THE UI HERE BUT THIS DOES NOT HAPPEN.

#### Comments

When viewed in summary like this the flow makes sense but for the first time InactiveCSS added logic that needs to be live i.e. can't simply be updated when there is a change in the UI.

The larger problem here is that adding more complexity here will make this code even more unmaintainable but I don't believe we have a choice.

### Detail

#### We immediately update the UI (Detail)

1. The checkbox next to `display:flex` is clicked, disabling the property:
   CLIENT [text-property::setEnabled()]
   CLIENT [rule::setPropertyEnabled]

2. We update the editor (crossing out and re-evaluating isUsed for `display:flex`):
   CLIENT [text-property::updateEditor()]
   CLIENT [text-property-editor::update]
   CLIENT [text-property-editor::updatePropertyState]
   CLIENT [text-property:isUsed] display::used = true
   CLIENT [text-property-editor::updatePropertyState] display::used = true

3. The client emits `property-value-updated`:
   EMITTING: emit(property-value-updated, {rule: [object Object], property: display, value: flex}) from update@resource://devtools/client/inspector/rules/views/text-property-editor.js:516:19

4. The server emits `track-change` along with the changes:
   EMITTING: emit(track-change, {id: server0.conn0.child1/domstylerule50, ancestors: , selector: div, source: [object Object], ruleIndex: 0, type: declaration-disable, add: null, remove: [object Object]}) from trackChange@resource://devtools/server/actors/utils/track-change-emitter.js:22:10

5. The `track-change` data is stored
   ?????? [event-emitter::bound pushChange] (
   {},
   {id: server0.conn0.child1/domstylerule50, ancestors: , selector: div, source: [object Object], ruleIndex: 0, type: declaration-disable, add: null, remove: [object Object]},
   )
   SERVER [string::initialize] (
   {},
   {\_prefix: server0.conn0.child1/, \_transport: [object Object], \_nextID: 58, \_socketListener: null, \_actorPool: [object Object], \_extraPools: [object Object],[object Object],[object Object],[Actor frame..., \_actorResponses: [object Map], \_forwardingPrefixes: [object Map], parentMessageManager: [object ContentFrameMessageManager], currentPacket: undefined},
   )

6. Changes are queued for the `div` rule along with `display:flex`:
   ?????? [lexer::map] (
   div,
   function anonymous(),
   )
   ?????? [lexer::map] (
   display,
   function anonymous(),
   )
   ?????? [lexer::map] (
   flex,
   function anonymous(),
   )

#### We apply the changes to the stylesheets (Detail)

1. stylesheets::update() is called to update the style sheet in place with new text:
   SERVER [stylesheets::update]
   SERVER [stylesheets::update] sending style-applied event
   EMITTING: emit(style-applied, 0, {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]}) from update@resource://devtools/server/actors/stylesheets.js:583:12
   ?????? [event-emitter::anonymous] (
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   0,
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   )

2. A `style-applied` event is triggered causing the `styles::_styleApplied()` method to reset `cssLogic`:
   ?????? [event-emitter::bound _styleApplied] (
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   0,
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   )
   SERVER [styles::_styleApplied]
   SERVER [styles::_styleApplied] calling cssLogic.reset()

3. The `style-applied` event is triggered:
   ?????? [event-emitter::bound _onStyleApplied] (
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1
   EMITTING: emit(style-applied, 0, {conn: [object Object], \_\_poolMap: null, actorID: server0.conn0.child1/stylesheet40, \_requests: , \_frontListeners: [object Object], \_beforeListeners: [object Map], \_onPropertyChange: function() {
   [native code]
   }, \_form: [object Object]}) from onPacket@resource://devtools/shared/protocol/Front.js:200:13
   ], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   0,
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   )

4. `styles::_onStyleApplied()` is called for the `div` rule.
   SERVER [styles::_onStyleApplied] this.\_ruleIndex = 1
   EMITTING: emit(location-changed, 1, 29) from \_notifyLocationChanged@resource://devtools/server/ actors/styles.js:1565:10
   ?????? [event-emitter::anonymous] (
   {actorID: server0.conn0.child1/domstylerule49, \_actorSpec: [object Object], pageStyle: [Actor pagestyle/server0.conn0.child1/pagestyle24], rawStyle: [object CSS2Properties], \_parentSheet: [object CSSStyleSheet], \_onStyleApplied: function() {
   [native code]
   }, \_declarations: [object Object], type: 1, rawRule: [object CSSStyleRule], \_ruleIndex: 1},
   1,
   29,
   )
   ?????? [event-emitter::bound _onStyleApplied] (
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   0,
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   )

5. `styles::_onStyleApplied()` is called for the `.end` rule.
   SERVER [styles::_onStyleApplied] this.\_ruleIndex = 0

6. `stylesheets::update()` sends a `media-rules-changed` event:
   SERVER [stylesheets::update] sending media-rules-changed event
   EMITTING: emit(media-rules-changed, []) from update/<@resource://devtools/server/actors stylesheets.js:590:12
   EMITTING: emit(location-changed, 1, 29) from onPacket@resource://devtools/shared/protocol Front.js:200:13
   ?????? [event-emitter::anonymous] (
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   [],
   )

7. The rule URL is updated:
   EMITTING: emit(source-link-updated) from updateSourceLink/<@resource://devtools/client/inspector/ rules/views/rule-editor.js:429:12
   ?????? [lexer::map] (
   display,
   function anonymous(),
   )
   ?????? [lexer::map] (
   flex,
   function anonymous(),
   )

8. A `media-rules-changed` (I don't think this affects the rule view):

   EMITTING: emit(media-rules-changed, []) from onPacket@resource://devtools/shared/protocol/Front.js:200:13

9. [styles::form] is triggered recalculating `isUsed` for `div`:
   SERVER [styles::form] Recalculating isUsed for div
   SERVER [styles::form] display::used = true

10. `onRuleUpdated()` is called:
    CLIENT [rule::applyProperties] Calling onRuleUpdated()
    CLIENT [element-style::onRuleUpdated]

11. We call `element-style::updateDeclarations()`:
    CLIENT [element-style::updateDeclarations]

12. We try to update the property state but WRONGLY believe that `justify-content::used = true` because the style change has not yet been applied to the content:
    CLIENT [text-property-editor::updatePropertyState]
    CLIENT [text-property:isUsed] justify-content::used = true
    CLIENT [text-property-editor::updatePropertyState] justify-content::used = true

#### We respond to the reflows (Details)

1. At this point we realize that something changed in the rule view:
   EMITTING: emit(ruleview-changed) from \_changed@resource://devtools/client/inspector/rules/rules.js:1127:10

2. The reflow actor also notices these changes and sends a `reflows` event:
   EMITTING: emit(reflows, [{start:8204.813903, end:8204.941783, isInterruptible:true}]) from \_startEventLoop@resource://devtools/server/actors/reflow.js:315:12
   ?????? [event-emitter::bound _onReflows] (
   {targetActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], \_startEventLoop: function() {
   [native code]
   }, \_onReflow: function() {
   [native code]
   }, \_onResize: function() {
   [native code]
   }, reflowObserver: [object Object], resizeObserver: [object Object], isObserving: true, reflows: [object Object], hasResized: false, eventLoopTimer: 1155},
   [{start:8204.813903, end:8204.941783, isInterruptible:true}],
   )

3. The `reflows` actor tells us which node has changed:
   EMITTING: emit(display-change, ) from \_onReflows@resource://devtools/server/actors/inspector walker.js:591:12
   ?????? [event-emitter::anonymous]

4. A second `reflows` event:
   ?????? [event-emitter::bound _onReflow] (
   {targetActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], \_startEventLoop: function() {
   [native code]
   }, \_onReflow: function() {
   [native code]
   }, \_onResize: function() {
   [native code]
   }, reflowObserver: [object Object], resizeObserver: [object Object], isObserving: true, reflows: [object Object], hasResized: false, eventLoopTimer: 1155},
   [{start:8204.813903, end:8204.941783, isInterruptible:true}],
   )
   EMITTING: emit(reflows, [{start:8204.813903, end:8204.941783, isInterruptible:true}]) from \_onReflow@resource://devtools/server/actors/reflow.js:81:12
   ?????? [event-emitter::anonymous] (
   {conn: [object Object], actorID: server0.conn0.child1/reflowActor8, \_actorSpec: [object Object], targetActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], \_onReflow: function() {
   [native code]
   }, observer: [object Object], \_isStarted: true, \_pendingResponse: [object Promise]},
   [{start:8204.813903, end:8204.941783, isInterruptible:true}],
   )

5. The second `reflows` actor tells us which node has changed:
   EMITTING: emit(display-change, [{conn:{\_transport:{other:{other:{}, hooks:{\_prefix:"server0...) from onPacket@resource://devtools/shared/protocol/Front.js:200:13
   EMITTING: emit(reflows, [{start:8204.813903, end:8204.941783, isInterruptible:true}]) from onPacket@resource://devtools/shared/protocol/Front.js:200:13

6. CSSLogic now rebuilds its list of rules for all stylesheets:
   SERVER [css-logic::_processMatchedSelector] (
   {\_cssLogic: [object Object], property: margin-top, \_value: , \_matchedSelectors: , needRefilter: false},
   {cssRule: [CssRule div], text: div, inlineStyle: false, \_specificity: null, selectorIndex: 0, \_matchId: 6},
   2,
   0,
   )
   SERVER [css-logic::_processMatchedSelector] (
   {\_cssLogic: [object Object], property: margin-top, \_value: , \_matchedSelectors: , needRefilter: false},
   {cssRule: [CssRule .end], text: .end, inlineStyle: false, \_specificity: null, selectorIndex: 0, \_matchId: 6},
   2,
   0,
   )
   SERVER [css-logic::_processMatchedSelector] (
   {\_cssLogic: [object Object], property: margin-bottom, \_value: , \_matchedSelectors: , needRefilter: false},
   {cssRule: [CssRule div], text: div, inlineStyle: false, \_specificity: null, selectorIndex: 0, \_matchId: 6},
   2,
   )
   SERVER [css-logic::_processMatchedSelector] (
   {\_cssLogic: [object Object], property: margin-bottom, \_value: , \_matchedSelectors: , needRefilter: false},
   {cssRule: [CssRule .end], text: .end, inlineStyle: false, \_specificity: null, selectorIndex: 0, \_matchId: 6},
   2,
   )
   SERVER [css-logic::_processMatchedSelector] (
   {\_cssLogic: [object Object], property: margin-left, \_value: , \_matchedSelectors: , needRefilter: false},
   {cssRule: [CssRule div], text: div, inlineStyle: false, \_specificity: null, selectorIndex: 0, \_matchId: 6},
   2,
   )
   SERVER [css-logic::_processMatchedSelector] (
   {\_cssLogic: [object Object], property: margin-left, \_value: , \_matchedSelectors: , needRefilter: false},
   {cssRule: [CssRule .end], text: .end, inlineStyle: false, \_specificity: null, selectorIndex: 0, \_matchId: 6},
   2,
   )
   SERVER [css-logic::_processMatchedSelector] (
   {\_cssLogic: [object Object], property: margin-right, \_value: , \_matchedSelectors: , needRefilter: false},
   {cssRule: [CssRule div], text: div, inlineStyle: false, \_specificity: null, selectorIndex: 0, \_matchId: 6},
   2,
   )
   SERVER [css-logic::_processMatchedSelector] (
   {\_cssLogic: [object Object], property: margin-right, \_value: , \_matchedSelectors: , needRefilter: false},
   {cssRule: [CssRule .end], text: .end, inlineStyle: false, \_specificity: null, selectorIndex: 0, \_matchId: 6},
   2,
   )
   SERVER [css-logic::forEach] (
   [{}],
   function \_cacheSheet(),
   {\_propertyInfos: [object Object], viewedElement: [object HTMLDivElement], viewedDocument: [object HTMLDocument], \_passId: 34, \_ruleCount: 0, \_sheetIndex: 0, \_sheets: [object Object], \_sheetsCached: false, \_matchedRules: null, \_matchedSelectors: null},
   )
   ?????? [lexer::map] (
   justify-content,
   function anonymous(),
   )
   ?????? [lexer::map] (
   end,
   function anonymous(),
   )

7. `styles::form()` is called updating `isUsed` for `justify:content` AND GETTING THE CORRECT RESULT THIS TIME:
   SERVER [styles::form] Recalculating isUsed for .end
   SERVER [inactive-property-helper::VALIDATORS] !this.gridContainer" true
   SERVER [inactive-property-helper::VALIDATORS] !this.flexContainer" true
   SERVER [styles::form] justify-content::used = false
   ?????? [lexer::map] (
   display,
   function anonymous(),
   )
   ?????? [lexer::map] (
   flex,
   function anonymous(),
   )

8. `styles::form()` is called updating `isUsed` for `display:flex`):
   SERVER [styles::form] Recalculating isUsed for div
   SERVER [styles::form] display::used = true
   EMITTING: emit(boxmodel-view-updated, []) from updateBoxModel/lastRequest<@resource://devtools client/inspector/boxmodel/box-model.js:217:22
   EMITTING: emit(hidden) from hide@resource://devtools/client/shared/widgets/tooltip HTMLTooltip.js:764:12
   EMITTING: emit(hidden) from hide@resource://devtools/client/shared/widgets/tooltip HTMLTooltip.js:764:12

#### The problem (Details)

1. WE SHOULD UPDATE THE UI HERE BUT THIS DOES NOT HAPPEN.
## Take this CSS

```css
.end {
  justify-content: end;
}

div {
  display: flex;
}
```

## This is what happens:

### Summary

#### We immediately update the UI

1. The checkbox next to `display:flex` is clicked, disabling the property.
2. We update the editor (crossing out and re-evaluating isUsed for `display:flex`).
3. The client emits `property-value-updated`.
4. The server emits `track-change` along with the changes.
5. The `track-change` data is stored.
6. Changes are queued for the `div` rule along with `display:flex`.

#### We apply the changes to the stylesheets

1. `stylesheets::update()` is called to update the style sheet in place with new text.
2. A `style-applied` event is triggered causing the `styles::_styleApplied()` method to reset `cssLogic`.
3. The `style-applied` event is triggered.
4. `styles::_onStyleApplied()` is called for the `div` rule.
5. `styles::_onStyleApplied()` is called for the `.end` rule.
6. `stylesheets::update()` sends a `media-rules-changed` event.
7. The rule URL is updated.
8. A `media-rules-changed` (I don't think this affects the rule view).
9. [styles::form] is triggered recalculating `isUsed` for `div`.
10. `onRuleUpdated()` is called.
11. We call `element-style::updateDeclarations()`.
12. We try to update the property state but WRONGLY believe that `justify-content::used = true` because the style change has not yet been applied to the content.

#### We respond to the reflows

1. At this point we realize that something changed in the rule view.
2. The reflow actor also notices these changes and sends a `reflows` event.
3. The `reflows` actor tells us which node has changed.
4. A second `reflows` event.
5. The second `reflows` actor tells us which node has changed.
6. CSSLogic now rebuilds its list of rules for all stylesheets.
7. `styles::form()` is called updating `isUsed` for `justify:content` AND GETTING THE CORRECT RESULT THIS TIME.
8. `styles::form()` is called updating `isUsed` for `display:flex`).

#### The problem

1. WE SHOULD UPDATE THE UI HERE BUT THIS DOES NOT HAPPEN.

#### Comments

When viewed in summary like this the flow makes sense but for the first time InactiveCSS added logic that needs to be live i.e. can't simply be updated when there is a change in the UI.

The larger problem here is that adding more complexity here will make this code even more unmaintainable but I don't believe we have a choice.

### Detail

#### We immediately update the UI (Detail)

1. The checkbox next to `display:flex` is clicked, disabling the property:
   CLIENT [text-property::setEnabled()]
   CLIENT [rule::setPropertyEnabled]

2. We update the editor (crossing out and re-evaluating isUsed for `display:flex`):
   CLIENT [text-property::updateEditor()]
   CLIENT [text-property-editor::update]
   CLIENT [text-property-editor::updatePropertyState]
   CLIENT [text-property:isUsed] display::used = true
   CLIENT [text-property-editor::updatePropertyState] display::used = true

3. The client emits `property-value-updated`:
   EMITTING: emit(property-value-updated, {rule: [object Object], property: display, value: flex}) from update@resource://devtools/client/inspector/rules/views/text-property-editor.js:516:19

4. The server emits `track-change` along with the changes:
   EMITTING: emit(track-change, {id: server0.conn0.child1/domstylerule50, ancestors: , selector: div, source: [object Object], ruleIndex: 0, type: declaration-disable, add: null, remove: [object Object]}) from trackChange@resource://devtools/server/actors/utils/track-change-emitter.js:22:10

5. The `track-change` data is stored
   ?????? [event-emitter::bound pushChange] (
   {},
   {id: server0.conn0.child1/domstylerule50, ancestors: , selector: div, source: [object Object], ruleIndex: 0, type: declaration-disable, add: null, remove: [object Object]},
   )
   SERVER [string::initialize] (
   {},
   {\_prefix: server0.conn0.child1/, \_transport: [object Object], \_nextID: 58, \_socketListener: null, \_actorPool: [object Object], \_extraPools: [object Object],[object Object],[object Object],[Actor frame..., \_actorResponses: [object Map], \_forwardingPrefixes: [object Map], parentMessageManager: [object ContentFrameMessageManager], currentPacket: undefined},
   )

6. Changes are queued for the `div` rule along with `display:flex`:
   ?????? [lexer::map] (
   div,
   function anonymous(),
   )
   ?????? [lexer::map] (
   display,
   function anonymous(),
   )
   ?????? [lexer::map] (
   flex,
   function anonymous(),
   )

#### We apply the changes to the stylesheets (Detail)

1. `stylesheets::update()` is called to update the style sheet in place with new text:
   SERVER [stylesheets::update]
   SERVER [stylesheets::update] sending style-applied event
   EMITTING: emit(style-applied, 0, {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]}) from update@resource://devtools/server/actors/stylesheets.js:583:12
   ?????? [event-emitter::anonymous] (
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   0,
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   )

2. A `style-applied` event is triggered causing the `styles::_styleApplied()` method to reset `cssLogic`:
   ?????? [event-emitter::bound _styleApplied] (
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   0,
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   )
   SERVER [styles::_styleApplied]
   SERVER [styles::_styleApplied] calling cssLogic.reset()

3. The `style-applied` event is triggered:
   ?????? [event-emitter::bound _onStyleApplied] (
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1
   EMITTING: emit(style-applied, 0, {conn: [object Object], \_\_poolMap: null, actorID: server0.conn0.child1/stylesheet40, \_requests: , \_frontListeners: [object Object], \_beforeListeners: [object Map], \_onPropertyChange: function() {
   [native code]
   }, \_form: [object Object]}) from onPacket@resource://devtools/shared/protocol/Front.js:200:13
   ], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   0,
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   )

4. `styles::_onStyleApplied()` is called for the `div` rule.
   SERVER [styles::_onStyleApplied] this.\_ruleIndex = 1
   EMITTING: emit(location-changed, 1, 29) from \_notifyLocationChanged@resource://devtools/server/ actors/styles.js:1565:10
   ?????? [event-emitter::anonymous] (
   {actorID: server0.conn0.child1/domstylerule49, \_actorSpec: [object Object], pageStyle: [Actor pagestyle/server0.conn0.child1/pagestyle24], rawStyle: [object CSS2Properties], \_parentSheet: [object CSSStyleSheet], \_onStyleApplied: function() {
   [native code]
   }, \_declarations: [object Object], type: 1, rawRule: [object CSSStyleRule], \_ruleIndex: 1},
   1,
   29,
   )
   ?????? [event-emitter::bound _onStyleApplied] (
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   0,
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   )

5. `styles::_onStyleApplied()` is called for the `.end` rule.
   SERVER [styles::_onStyleApplied] this.\_ruleIndex = 0

6. `stylesheets::update()` sends a `media-rules-changed` event:
   SERVER [stylesheets::update] sending media-rules-changed event
   EMITTING: emit(media-rules-changed, []) from update/<@resource://devtools/server/actors stylesheets.js:590:12
   EMITTING: emit(location-changed, 1, 29) from onPacket@resource://devtools/shared/protocol Front.js:200:13
   ?????? [event-emitter::anonymous] (
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   [],
   )

7. The rule URL is updated:
   EMITTING: emit(source-link-updated) from updateSourceLink/<@resource://devtools/client/inspector/ rules/views/rule-editor.js:429:12
   ?????? [lexer::map] (
   display,
   function anonymous(),
   )
   ?????? [lexer::map] (
   flex,
   function anonymous(),
   )

8. A `media-rules-changed` (I don't think this affects the rule view):

   EMITTING: emit(media-rules-changed, []) from onPacket@resource://devtools/shared/protocol/Front.js:200:13

9. [styles::form] is triggered recalculating `isUsed` for `div`:
   SERVER [styles::form] Recalculating isUsed for div
   SERVER [styles::form] display::used = true

10. `onRuleUpdated()` is called:
    CLIENT [rule::applyProperties] Calling onRuleUpdated()
    CLIENT [element-style::onRuleUpdated]

11. We call `element-style::updateDeclarations()`:
    CLIENT [element-style::updateDeclarations]

12. We try to update the property state but WRONGLY believe that `justify-content::used = true` because the style change has not yet been applied to the content:
    CLIENT [text-property-editor::updatePropertyState]
    CLIENT [text-property:isUsed] justify-content::used = true
    CLIENT [text-property-editor::updatePropertyState] justify-content::used = true

#### We respond to the reflows (Details)

1. At this point we realize that something changed in the rule view:
   EMITTING: emit(ruleview-changed) from \_changed@resource://devtools/client/inspector/rules/rules.js:1127:10

2. The reflow actor also notices these changes and sends a `reflows` event:
   EMITTING: emit(reflows, [{start:8204.813903, end:8204.941783, isInterruptible:true}]) from \_startEventLoop@resource://devtools/server/actors/reflow.js:315:12
   ?????? [event-emitter::bound _onReflows] (
   {targetActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], \_startEventLoop: function() {
   [native code]
   }, \_onReflow: function() {
   [native code]
   }, \_onResize: function() {
   [native code]
   }, reflowObserver: [object Object], resizeObserver: [object Object], isObserving: true, reflows: [object Object], hasResized: false, eventLoopTimer: 1155},
   [{start:8204.813903, end:8204.941783, isInterruptible:true}],
   )

3. The `reflows` actor tells us which node has changed:
   EMITTING: emit(display-change, ) from \_onReflows@resource://devtools/server/actors/inspector walker.js:591:12
   ?????? [event-emitter::anonymous]

4. A second `reflows` event:
   ?????? [event-emitter::bound _onReflow] (
   {targetActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], \_startEventLoop: function() {
   [native code]
   }, \_onReflow: function() {
   [native code]
   }, \_onResize: function() {
   [native code]
   }, reflowObserver: [object Object], resizeObserver: [object Object], isObserving: true, reflows: [object Object], hasResized: false, eventLoopTimer: 1155},
   [{start:8204.813903, end:8204.941783, isInterruptible:true}],
   )
   EMITTING: emit(reflows, [{start:8204.813903, end:8204.941783, isInterruptible:true}]) from \_onReflow@resource://devtools/server/actors/reflow.js:81:12
   ?????? [event-emitter::anonymous] (
   {conn: [object Object], actorID: server0.conn0.child1/reflowActor8, \_actorSpec: [object Object], targetActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], \_onReflow: function() {
   [native code]
   }, observer: [object Object], \_isStarted: true, \_pendingResponse: [object Promise]},
   [{start:8204.813903, end:8204.941783, isInterruptible:true}],
   )

5. The second `reflows` actor tells us which node has changed:
   EMITTING: emit(display-change, [{conn:{\_transport:{other:{other:{}, hooks:{\_prefix:"server0...) from onPacket@resource://devtools/shared/protocol/Front.js:200:13
   EMITTING: emit(reflows, [{start:8204.813903, end:8204.941783, isInterruptible:true}]) from onPacket@resource://devtools/shared/protocol/Front.js:200:13

6. CSSLogic now rebuilds its list of rules for all stylesheets:
   SERVER [css-logic::_processMatchedSelector] (
   {\_cssLogic: [object Object], property: margin-top, \_value: , \_matchedSelectors: , needRefilter: false},
   {cssRule: [CssRule div], text: div, inlineStyle: false, \_specificity: null, selectorIndex: 0, \_matchId: 6},
   2,
   0,
   )
   SERVER [css-logic::_processMatchedSelector] (
   {\_cssLogic: [object Object], property: margin-top, \_value: , \_matchedSelectors: , needRefilter: false},
   {cssRule: [CssRule .end], text: .end, inlineStyle: false, \_specificity: null, selectorIndex: 0, \_matchId: 6},
   2,
   0,
   )
   SERVER [css-logic::_processMatchedSelector] (
   {\_cssLogic: [object Object], property: margin-bottom, \_value: , \_matchedSelectors: , needRefilter: false},
   {cssRule: [CssRule div], text: div, inlineStyle: false, \_specificity: null, selectorIndex: 0, \_matchId: 6},
   2,
   )
   SERVER [css-logic::_processMatchedSelector] (
   {\_cssLogic: [object Object], property: margin-bottom, \_value: , \_matchedSelectors: , needRefilter: false},
   {cssRule: [CssRule .end], text: .end, inlineStyle: false, \_specificity: null, selectorIndex: 0, \_matchId: 6},
   2,
   )
   SERVER [css-logic::_processMatchedSelector] (
   {\_cssLogic: [object Object], property: margin-left, \_value: , \_matchedSelectors: , needRefilter: false},
   {cssRule: [CssRule div], text: div, inlineStyle: false, \_specificity: null, selectorIndex: 0, \_matchId: 6},
   2,
   )
   SERVER [css-logic::_processMatchedSelector] (
   {\_cssLogic: [object Object], property: margin-left, \_value: , \_matchedSelectors: , needRefilter: false},
   {cssRule: [CssRule .end], text: .end, inlineStyle: false, \_specificity: null, selectorIndex: 0, \_matchId: 6},
   2,
   )
   SERVER [css-logic::_processMatchedSelector] (
   {\_cssLogic: [object Object], property: margin-right, \_value: , \_matchedSelectors: , needRefilter: false},
   {cssRule: [CssRule div], text: div, inlineStyle: false, \_specificity: null, selectorIndex: 0, \_matchId: 6},
   2,
   )
   SERVER [css-logic::_processMatchedSelector] (
   {\_cssLogic: [object Object], property: margin-right, \_value: , \_matchedSelectors: , needRefilter: false},
   {cssRule: [CssRule .end], text: .end, inlineStyle: false, \_specificity: null, selectorIndex: 0, \_matchId: 6},
   2,
   )
   SERVER [css-logic::forEach] (
   [{}],
   function \_cacheSheet(),
   {\_propertyInfos: [object Object], viewedElement: [object HTMLDivElement], viewedDocument: [object HTMLDocument], \_passId: 34, \_ruleCount: 0, \_sheetIndex: 0, \_sheets: [object Object], \_sheetsCached: false, \_matchedRules: null, \_matchedSelectors: null},
   )
   ?????? [lexer::map] (
   justify-content,
   function anonymous(),
   )
   ?????? [lexer::map] (
   end,
   function anonymous(),
   )

7. `styles::form()` is called updating `isUsed` for `justify:content` AND GETTING THE CORRECT RESULT THIS TIME:
   SERVER [styles::form] Recalculating isUsed for .end
   SERVER [inactive-property-helper::VALIDATORS] !this.gridContainer" true
   SERVER [inactive-property-helper::VALIDATORS] !this.flexContainer" true
   SERVER [styles::form] justify-content::used = false
   ?????? [lexer::map] (
   display,
   function anonymous(),
   )
   ?????? [lexer::map] (
   flex,
   function anonymous(),
   )

8. `styles::form()` is called updating `isUsed` for `display:flex`):
   SERVER [styles::form] Recalculating isUsed for div
   SERVER [styles::form] display::used = true
   EMITTING: emit(boxmodel-view-updated, []) from updateBoxModel/lastRequest<@resource://devtools client/inspector/boxmodel/box-model.js:217:22
   EMITTING: emit(hidden) from hide@resource://devtools/client/shared/widgets/tooltip HTMLTooltip.js:764:12
   EMITTING: emit(hidden) from hide@resource://devtools/client/shared/widgets/tooltip HTMLTooltip.js:764:12

#### The problem (Details)

1. WE SHOULD UPDATE THE UI HERE BUT THIS DOES NOT HAPPEN.
## Take this CSS

```css
.end {
  justify-content: end;
}

div {
  display: flex;
}
```

## This is what happens:

### Summary

#### We immediately update the UI

1. The checkbox next to `display:flex` is clicked, disabling the property.
2. We update the editor (crossing out and re-evaluating isUsed for `display:flex`).
3. The client emits `property-value-updated`.
4. The server emits `track-change` along with the changes.
5. The `track-change` data is stored.
6. Changes are queued for the `div` rule along with `display:flex`.

#### We apply the changes to the stylesheets

1. `stylesheets::update()` is called to update the style sheet in place with new text.
2. A `style-applied` event is triggered causing the `styles::_styleApplied()` method to reset `cssLogic`.
3. The `style-applied` event is triggered.
4. `styles::_onStyleApplied()` is called for the `div` rule.
5. `styles::_onStyleApplied()` is called for the `.end` rule.
6. `stylesheets::update()` sends a `media-rules-changed` event.
7. The rule URL is updated.
8. A `media-rules-changed` (I don't think this affects the rule view).
9. [styles::form] is triggered recalculating `isUsed` for `div`.
10. `onRuleUpdated()` is called.
11. We call `element-style::updateDeclarations()`.
12. We try to update the property state but WRONGLY believe that `justify-content::used = true` because the style change has not yet been applied to the content.

#### We respond to the reflows

1. At this point we realize that something changed in the rule view.
2. The reflow actor also notices these changes and sends a `reflows` event.
3. The `reflows` actor tells us which node has changed.
4. A second `reflows` event.

#### The problem

1. WE SHOULD UPDATE THE UI HERE BUT THIS DOES NOT HAPPEN.

#### Comments

When viewed in summary like this the flow makes sense but for the first time InactiveCSS added logic that needs to be live i.e. can't simply be updated when there is a change in the UI.

The larger problem here is that adding more complexity here will make this code even more unmaintainable but I don't believe we have a choice.

### Detail

#### We immediately update the UI (Detail)

1. The checkbox next to `display:flex` is clicked, disabling the property:
   CLIENT [text-property::setEnabled()]
   CLIENT [rule::setPropertyEnabled]

2. We update the editor (crossing out and re-evaluating isUsed for `display:flex`):
   CLIENT [text-property::updateEditor()]
   CLIENT [text-property-editor::update]
   CLIENT [text-property-editor::updatePropertyState]
   CLIENT [text-property:isUsed] display::used = true
   CLIENT [text-property-editor::updatePropertyState] display::used = true

3. The client emits `property-value-updated`:
   EMITTING: emit(property-value-updated, {rule: [object Object], property: display, value: flex}) from update@resource://devtools/client/inspector/rules/views/text-property-editor.js:516:19

4. The server emits `track-change` along with the changes:
   EMITTING: emit(track-change, {id: server0.conn0.child1/domstylerule50, ancestors: , selector: div, source: [object Object], ruleIndex: 0, type: declaration-disable, add: null, remove: [object Object]}) from trackChange@resource://devtools/server/actors/utils/track-change-emitter.js:22:10

5. The `track-change` data is stored
   ?????? [event-emitter::bound pushChange] (
   {},
   {id: server0.conn0.child1/domstylerule50, ancestors: , selector: div, source: [object Object], ruleIndex: 0, type: declaration-disable, add: null, remove: [object Object]},
   )
   SERVER [string::initialize] (
   {},
   {\_prefix: server0.conn0.child1/, \_transport: [object Object], \_nextID: 58, \_socketListener: null, \_actorPool: [object Object], \_extraPools: [object Object],[object Object],[object Object],[Actor frame..., \_actorResponses: [object Map], \_forwardingPrefixes: [object Map], parentMessageManager: [object ContentFrameMessageManager], currentPacket: undefined},
   )

6. Changes are queued for the `div` rule along with `display:flex`:
   ?????? [lexer::map] (
   div,
   function anonymous(),
   )
   ?????? [lexer::map] (
   display,
   function anonymous(),
   )
   ?????? [lexer::map] (
   flex,
   function anonymous(),
   )

#### We apply the changes to the stylesheets (Detail)

1. `stylesheets::update()` is called to update the style sheet in place with new text:
   SERVER [stylesheets::update]
   SERVER [stylesheets::update] sending style-applied event
   EMITTING: emit(style-applied, 0, {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]}) from update@resource://devtools/server/actors/stylesheets.js:583:12
   ?????? [event-emitter::anonymous] (
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   0,
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   )

2. A `style-applied` event is triggered causing the `styles::_styleApplied()` method to reset `cssLogic`:
   ?????? [event-emitter::bound _styleApplied] (
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   0,
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   )
   SERVER [styles::_styleApplied]
   SERVER [styles::_styleApplied] calling cssLogic.reset()

3. The `style-applied` event is triggered:
   ?????? [event-emitter::bound _onStyleApplied] (
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1
   EMITTING: emit(style-applied, 0, {conn: [object Object], \_\_poolMap: null, actorID: server0.conn0.child1/stylesheet40, \_requests: , \_frontListeners: [object Object], \_beforeListeners: [object Map], \_onPropertyChange: function() {
   [native code]
   }, \_form: [object Object]}) from onPacket@resource://devtools/shared/protocol/Front.js:200:13
   ], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   0,
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   )

4. `styles::_onStyleApplied()` is called for the `div` rule.
   SERVER [styles::_onStyleApplied] this.\_ruleIndex = 1
   EMITTING: emit(location-changed, 1, 29) from \_notifyLocationChanged@resource://devtools/server/ actors/styles.js:1565:10
   ?????? [event-emitter::anonymous] (
   {actorID: server0.conn0.child1/domstylerule49, \_actorSpec: [object Object], pageStyle: [Actor pagestyle/server0.conn0.child1/pagestyle24], rawStyle: [object CSS2Properties], \_parentSheet: [object CSSStyleSheet], \_onStyleApplied: function() {
   [native code]
   }, \_declarations: [object Object], type: 1, rawRule: [object CSSStyleRule], \_ruleIndex: 1},
   1,
   29,
   )
   ?????? [event-emitter::bound _onStyleApplied] (
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   0,
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   )

5. `styles::_onStyleApplied()` is called for the `.end` rule.
   SERVER [styles::_onStyleApplied] this.\_ruleIndex = 0

6. `stylesheets::update()` sends a `media-rules-changed` event:
   SERVER [stylesheets::update] sending media-rules-changed event
   EMITTING: emit(media-rules-changed, []) from update/<@resource://devtools/server/actors stylesheets.js:590:12
   EMITTING: emit(location-changed, 1, 29) from onPacket@resource://devtools/shared/protocol Front.js:200:13
   ?????? [event-emitter::anonymous] (
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   [],
   )

7. The rule URL is updated:
   EMITTING: emit(source-link-updated) from updateSourceLink/<@resource://devtools/client/inspector/ rules/views/rule-editor.js:429:12
   ?????? [lexer::map] (
   display,
   function anonymous(),
   )
   ?????? [lexer::map] (
   flex,
   function anonymous(),
   )

8. A `media-rules-changed` (I don't think this affects the rule view):

   EMITTING: emit(media-rules-changed, []) from onPacket@resource://devtools/shared/protocol/Front.js:200:13

9. [styles::form] is triggered recalculating `isUsed` for `div`:
   SERVER [styles::form] Recalculating isUsed for div
   SERVER [styles::form] display::used = true

10. `onRuleUpdated()` is called:
    CLIENT [rule::applyProperties] Calling onRuleUpdated()
    CLIENT [element-style::onRuleUpdated]

11. We call `element-style::updateDeclarations()`:
    CLIENT [element-style::updateDeclarations]

12. We try to update the property state but WRONGLY believe that `justify-content::used = true` because the style change has not yet been applied to the content:
    CLIENT [text-property-editor::updatePropertyState]
    CLIENT [text-property:isUsed] justify-content::used = true
    CLIENT [text-property-editor::updatePropertyState] justify-content::used = true

#### We respond to the reflows (Details)

1. At this point we send a `ruleview-changed` event:
   EMITTING: emit(ruleview-changed) from \_changed@resource://devtools/client/inspector/rules/rules.js:1127:10

2. The reflow actor also notices these changes and sends a `reflows` event:
   EMITTING: emit(reflows, [{start:8204.813903, end:8204.941783, isInterruptible:true}]) from \_startEventLoop@resource://devtools/server/actors/reflow.js:315:12
   ?????? [event-emitter::bound _onReflows] (
   {targetActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], \_startEventLoop: function() {
   [native code]
   }, \_onReflow: function() {
   [native code]
   }, \_onResize: function() {
   [native code]
   }, reflowObserver: [object Object], resizeObserver: [object Object], isObserving: true, reflows: [object Object], hasResized: false, eventLoopTimer: 1155},
   [{start:8204.813903, end:8204.941783, isInterruptible:true}],
   )

3. The `reflows` actor tells us which node has changed:
   EMITTING: emit(display-change, ) from \_onReflows@resource://devtools/server/actors/inspector walker.js:591:12
   ?????? [event-emitter::anonymous]

4. A second `reflows` event:
   ?????? [event-emitter::bound _onReflow] (
   {targetActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], \_startEventLoop: function() {
   [native code]
   }, \_onReflow: function() {
   [native code]
   }, \_onResize: function() {
   [native code]
   }, reflowObserver: [object Object], resizeObserver: [object Object], isObserving: true, reflows: [object Object], hasResized: false, eventLoopTimer: 1155},
   [{start:8204.813903, end:8204.941783, isInterruptible:true}],
   )
   EMITTING: emit(reflows, [{start:8204.813903, end:8204.941783, isInterruptible:true}]) from \_onReflow@resource://devtools/server/actors/reflow.js:81:12
   ?????? [event-emitter::anonymous] (
   {conn: [object Object], actorID: server0.conn0.child1/reflowActor8, \_actorSpec: [object Object], targetActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], \_onReflow: function() {
   [native code]
   }, observer: [object Object], \_isStarted: true, \_pendingResponse: [object Promise]},
   [{start:8204.813903, end:8204.941783, isInterruptible:true}],
   )

#### The problem (Details)

1. WE SHOULD UPDATE THE UI HERE BUT THIS DOES NOT HAPPEN.
## Take this CSS

```css
.end {
  justify-content: end;
}

div {
  display: flex;
}
```

## This is what happens:

### Summary

#### We immediately update the UI

1. The checkbox next to `display:flex` is clicked, disabling the property.
2. We update the editor (crossing out and re-evaluating isUsed for `display:flex`).
3. The client emits `property-value-updated`.
4. The server emits `track-change` along with the changes.
5. The `track-change` data is stored.
6. Changes are queued for the `div` rule along with `display:flex`.

#### We apply the changes to the stylesheets

1. `stylesheets::update()` is called to update the style sheet in place with new text.
2. A `style-applied` event is triggered causing the `styles::_styleApplied()` method to reset `cssLogic`.
3. The `style-applied` event is triggered.
4. `styles::_onStyleApplied()` is called for the `div` rule.
5. `styles::_onStyleApplied()` is called for the `.end` rule.
6. `stylesheets::update()` sends a `media-rules-changed` event.
7. The rule URL is updated.
8. A `media-rules-changed` (I don't think this affects the rule view).
9. [styles::form] is triggered recalculating `isUsed` for `div`.
10. `onRuleUpdated()` is called.
11. We call `element-style::updateDeclarations()`.
12. We try to update the property state but WRONGLY believe that `justify-content::used = true` because the style change has not yet been applied to the content.

#### We fail to respond to the reflows

1. At this point we realize that something changed in the rule view.
2. The reflow actor also notices these changes and sends a `reflows` event.
3. The `reflows` actor tells us which node has changed.
4. A second `reflows` event.

#### The problem

1. WE SHOULD UPDATE THE UI HERE BUT THIS DOES NOT HAPPEN.

#### Comments

When viewed in summary like this the flow makes sense but for the first time InactiveCSS added logic that needs to be live i.e. can't simply be updated when there is a change in the UI.

The larger problem here is that adding more complexity here will make this code even more unmaintainable but I don't believe we have a choice.

### Detail

#### We immediately update the UI (Detail)

1. The checkbox next to `display:flex` is clicked, disabling the property:
   CLIENT [text-property::setEnabled()]
   CLIENT [rule::setPropertyEnabled]

2. We update the editor (crossing out and re-evaluating isUsed for `display:flex`):
   CLIENT [text-property::updateEditor()]
   CLIENT [text-property-editor::update]
   CLIENT [text-property-editor::updatePropertyState]
   CLIENT [text-property:isUsed] display::used = true
   CLIENT [text-property-editor::updatePropertyState] display::used = true

3. The client emits `property-value-updated`:
   EMITTING: emit(property-value-updated, {rule: [object Object], property: display, value: flex}) from update@resource://devtools/client/inspector/rules/views/text-property-editor.js:516:19

4. The server emits `track-change` along with the changes:
   EMITTING: emit(track-change, {id: server0.conn0.child1/domstylerule50, ancestors: , selector: div, source: [object Object], ruleIndex: 0, type: declaration-disable, add: null, remove: [object Object]}) from trackChange@resource://devtools/server/actors/utils/track-change-emitter.js:22:10

5. The `track-change` data is stored
   ?????? [event-emitter::bound pushChange] (
   {},
   {id: server0.conn0.child1/domstylerule50, ancestors: , selector: div, source: [object Object], ruleIndex: 0, type: declaration-disable, add: null, remove: [object Object]},
   )
   SERVER [string::initialize] (
   {},
   {\_prefix: server0.conn0.child1/, \_transport: [object Object], \_nextID: 58, \_socketListener: null, \_actorPool: [object Object], \_extraPools: [object Object],[object Object],[object Object],[Actor frame..., \_actorResponses: [object Map], \_forwardingPrefixes: [object Map], parentMessageManager: [object ContentFrameMessageManager], currentPacket: undefined},
   )

6. Changes are queued for the `div` rule along with `display:flex`:
   ?????? [lexer::map] (
   div,
   function anonymous(),
   )
   ?????? [lexer::map] (
   display,
   function anonymous(),
   )
   ?????? [lexer::map] (
   flex,
   function anonymous(),
   )

#### We apply the changes to the stylesheets (Detail)

1. `stylesheets::update()` is called to update the style sheet in place with new text:
   SERVER [stylesheets::update]
   SERVER [stylesheets::update] sending style-applied event
   EMITTING: emit(style-applied, 0, {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]}) from update@resource://devtools/server/actors/stylesheets.js:583:12
   ?????? [event-emitter::anonymous] (
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   0,
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   )

2. A `style-applied` event is triggered causing the `styles::_styleApplied()` method to reset `cssLogic`:
   ?????? [event-emitter::bound _styleApplied] (
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   0,
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   )
   SERVER [styles::_styleApplied]
   SERVER [styles::_styleApplied] calling cssLogic.reset()

3. The `style-applied` event is triggered:
   ?????? [event-emitter::bound _onStyleApplied] (
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1
   EMITTING: emit(style-applied, 0, {conn: [object Object], \_\_poolMap: null, actorID: server0.conn0.child1/stylesheet40, \_requests: , \_frontListeners: [object Object], \_beforeListeners: [object Map], \_onPropertyChange: function() {
   [native code]
   }, \_form: [object Object]}) from onPacket@resource://devtools/shared/protocol/Front.js:200:13
   ], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   0,
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   )

4. `styles::_onStyleApplied()` is called for the `div` rule.
   SERVER [styles::_onStyleApplied] this.\_ruleIndex = 1
   EMITTING: emit(location-changed, 1, 29) from \_notifyLocationChanged@resource://devtools/server/ actors/styles.js:1565:10
   ?????? [event-emitter::anonymous] (
   {actorID: server0.conn0.child1/domstylerule49, \_actorSpec: [object Object], pageStyle: [Actor pagestyle/server0.conn0.child1/pagestyle24], rawStyle: [object CSS2Properties], \_parentSheet: [object CSSStyleSheet], \_onStyleApplied: function() {
   [native code]
   }, \_declarations: [object Object], type: 1, rawRule: [object CSSStyleRule], \_ruleIndex: 1},
   1,
   29,
   )
   ?????? [event-emitter::bound _onStyleApplied] (
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   0,
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   )

5. `styles::_onStyleApplied()` is called for the `.end` rule.
   SERVER [styles::_onStyleApplied] this.\_ruleIndex = 0

6. `stylesheets::update()` sends a `media-rules-changed` event:
   SERVER [stylesheets::update] sending media-rules-changed event
   EMITTING: emit(media-rules-changed, []) from update/<@resource://devtools/server/actors stylesheets.js:590:12
   EMITTING: emit(location-changed, 1, 29) from onPacket@resource://devtools/shared/protocol Front.js:200:13
   ?????? [event-emitter::anonymous] (
   {actorID: server0.conn0.child1/stylesheet40, \_actorSpec: [object Object], rawSheet: [object CSSStyleSheet], parentActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], conn: [object Object], text: div { /_! display:flex _/ } .end{ justify-content: end }, \_styleSheetIndex: 0, ownerDocument: [object HTMLDocument]},
   [],
   )

7. The rule URL is updated:
   EMITTING: emit(source-link-updated) from updateSourceLink/<@resource://devtools/client/inspector/ rules/views/rule-editor.js:429:12
   ?????? [lexer::map] (
   display,
   function anonymous(),
   )
   ?????? [lexer::map] (
   flex,
   function anonymous(),
   )

8. A `media-rules-changed` (I don't think this affects the rule view):

   EMITTING: emit(media-rules-changed, []) from onPacket@resource://devtools/shared/protocol/Front.js:200:13

9. [styles::form] is triggered recalculating `isUsed` for `div`:
   SERVER [styles::form] Recalculating isUsed for div
   SERVER [styles::form] display::used = true

10. `onRuleUpdated()` is called:
    CLIENT [rule::applyProperties] Calling onRuleUpdated()
    CLIENT [element-style::onRuleUpdated]

11. We call `element-style::updateDeclarations()`:
    CLIENT [element-style::updateDeclarations]

12. We try to update the property state but WRONGLY believe that `justify-content::used = true` because the style change has not yet been applied to the content:
    CLIENT [text-property-editor::updatePropertyState]
    CLIENT [text-property:isUsed] justify-content::used = true
    CLIENT [text-property-editor::updatePropertyState] justify-content::used = true

#### We fail to respond to the reflows (Details)

1. At this point we send a `ruleview-changed` event:
   EMITTING: emit(ruleview-changed) from \_changed@resource://devtools/client/inspector/rules/rules.js:1127:10

2. The reflow actor also notices these changes and sends a `reflows` event:
   EMITTING: emit(reflows, [{start:8204.813903, end:8204.941783, isInterruptible:true}]) from \_startEventLoop@resource://devtools/server/actors/reflow.js:315:12
   ?????? [event-emitter::bound _onReflows] (
   {targetActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], \_startEventLoop: function() {
   [native code]
   }, \_onReflow: function() {
   [native code]
   }, \_onResize: function() {
   [native code]
   }, reflowObserver: [object Object], resizeObserver: [object Object], isObserving: true, reflows: [object Object], hasResized: false, eventLoopTimer: 1155},
   [{start:8204.813903, end:8204.941783, isInterruptible:true}],
   )

3. The `reflows` actor tells us which node has changed:
   EMITTING: emit(display-change, ) from \_onReflows@resource://devtools/server/actors/inspector walker.js:591:12
   ?????? [event-emitter::anonymous]

4. A second `reflows` event:
   ?????? [event-emitter::bound _onReflow] (
   {targetActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], \_startEventLoop: function() {
   [native code]
   }, \_onReflow: function() {
   [native code]
   }, \_onResize: function() {
   [native code]
   }, reflowObserver: [object Object], resizeObserver: [object Object], isObserving: true, reflows: [object Object], hasResized: false, eventLoopTimer: 1155},
   [{start:8204.813903, end:8204.941783, isInterruptible:true}],
   )
   EMITTING: emit(reflows, [{start:8204.813903, end:8204.941783, isInterruptible:true}]) from \_onReflow@resource://devtools/server/actors/reflow.js:81:12
   ?????? [event-emitter::anonymous] (
   {conn: [object Object], actorID: server0.conn0.child1/reflowActor8, \_actorSpec: [object Object], targetActor: [Actor frameTarget/server0.conn0.child1/frameTarget1], \_onReflow: function() {
   [native code]
   }, observer: [object Object], \_isStarted: true, \_pendingResponse: [object Promise]},
   [{start:8204.813903, end:8204.941783, isInterruptible:true}],
   )

#### The problem (Details)

1. WE SHOULD UPDATE THE UI HERE BUT THIS DOES NOT HAPPEN.

Back to Bug 1557689 Comment 2