fune/devtools/shared/specs/style-sheet.js
Nicolas Chevobbe ac3a027268 Bug 1679043 - [devtools] Fix race condition in StyleEditor when editing style sheet. r=daisuke,ochameau,devtools-backward-compat-reviewers,bomsy.
When the user edits a stylesheet in the StyleEditor, an `_isUpdating` flag is toggled,
and a request is sent to the server to actually apply those changes to the stylesheet.
It then causes a style-applied event to be emitted (or the stylesheet resource
to be updated, if watcher support is enabled for stylesheet).
In the end, this triggers the onStyleApplied function in the StyleEditor, where
we check if the `_isUpdating` flag is true (to know if the event was caused
through editing in style editor), and if not, replace the stylesheet content.

Unfortunately there's a race condition when the user is typing (and sending
multiple requests to the server), as the state of the _isUpdating flag could
be wrong if a new request is sent before the first one is handled.
This is probably highlighted with the throttling we're doing in the Resource API.

To fix this issue, we add a new `cause` parameter to the StyleSheets.update method,
which we set to `styleeditor` when calling update within the StyleEditor.
This `cause` parameter is then sent back by the server to the client (via the
style-applied event, or the resource update if we have Watcher support for stylesheets).
This `cause` can be checked by the StyleEditor client, and replace the check
on `_isUpdating`.

However, we need to keep the `_isUpdating` property to handle backward compatibility.

Differential Revision: https://phabricator.services.mozilla.com/D99862
2020-12-18 06:07:32 +00:00

58 lines
1.5 KiB
JavaScript

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {
Arg,
RetVal,
generateActorSpec,
types,
} = require("devtools/shared/protocol");
// Load the "mediarule" type used in this file.
require("devtools/shared/specs/media-rule");
types.addActorType("stylesheet");
const styleSheetSpec = generateActorSpec({
typeName: "stylesheet",
events: {
"property-change": {
type: "propertyChange",
property: Arg(0, "string"),
value: Arg(1, "json"),
},
"style-applied": {
type: "styleApplied",
kind: Arg(0, "number"),
styleSheet: Arg(1, "stylesheet"),
cause: Arg(2, "nullable:string"),
},
"media-rules-changed": {
type: "mediaRulesChanged",
rules: Arg(0, "array:mediarule"),
},
},
methods: {
// This is only called from StyleSheetFront#guessIndentation, which is only called
// from RuleRewriter#getDefaultIndentation when the rule's parent stylesheet isn't
// a resource. Once we support StyleSheet resource everywhere, this method can be
// removed (See Bug 1672090 for more information).
getText: {
response: {
text: RetVal("longstring"),
},
},
getMediaRules: {
request: {},
response: {
mediaRules: RetVal("nullable:array:mediarule"),
},
},
},
});
exports.styleSheetSpec = styleSheetSpec;