Skip to content
This repository was archived by the owner on Sep 6, 2021. It is now read-only.

Commit d8f8177

Browse files
committed
Merge pull request #7008 from adobe/jasonsanjose/issue-6830
Use styleSheetAdded and styleSheetRemoved, replaces getAllStylesheets
2 parents c59c542 + ac80eca commit d8f8177

6 files changed

Lines changed: 321 additions & 228 deletions

File tree

src/LiveDevelopment/Agents/CSSAgent.js

Lines changed: 110 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,25 @@
2828
/**
2929
* CSSAgent keeps track of loaded style sheets and allows reloading them
3030
* from a {Document}.
31+
*
32+
* CSSAgent dispatches styleSheetAdded and styleSheetRemoved events, passing
33+
* the URL for the added/removed style sheet.
3134
*/
32-
3335
define(function CSSAgent(require, exports, module) {
3436
"use strict";
3537

3638
require("thirdparty/path-utils/path-utils.min");
3739

3840
var Inspector = require("LiveDevelopment/Inspector/Inspector");
3941

40-
var _load; // {$.Deferred} load promise
41-
var _urlToStyle; // {url -> loaded} style definition
42+
/** @type {Object.<string, CSS.CSSStyleSheetHeader>} */
43+
var _urlToStyle = {};
44+
45+
/** @type {Object.<string, string>} */
46+
var _styleSheetIdToUrl;
47+
48+
/** @type {boolean} */
49+
var _getAllStyleSheetsNotFound = false;
4250

4351
/**
4452
* Create a canonicalized version of the given URL, stripping off query strings and hashes.
@@ -49,34 +57,31 @@ define(function CSSAgent(require, exports, module) {
4957
return PathUtils.parseUrl(url).hrefNoSearch;
5058
}
5159

52-
// WebInspector Event: Page.loadEventFired
53-
function _onLoadEventFired(event, res) {
54-
// res = {timestamp}
60+
/**
61+
* @private
62+
* WebInspector Event: Page.frameNavigated
63+
* @param {jQuery.Event} event
64+
* @param {frame: Frame} res
65+
*/
66+
function _onFrameNavigated(event, res) {
67+
// Clear maps when navigating to a new page
5568
_urlToStyle = {};
56-
Inspector.CSS.enable().done(function () {
57-
Inspector.CSS.getAllStyleSheets(function onGetAllStyleSheets(res) {
58-
var i, header;
59-
for (i in res.headers) {
60-
header = res.headers[i];
61-
_urlToStyle[_canonicalize(header.sourceURL)] = header;
62-
}
63-
_load.resolve();
64-
});
65-
});
69+
_styleSheetIdToUrl = {};
6670
}
6771

68-
/** Get a style sheet for a url
72+
/**
73+
* Get a style sheet for a url
6974
* @param {string} url
75+
* @return {CSS.CSSStyleSheetHeader}
7076
*/
7177
function styleForURL(url) {
72-
if (_urlToStyle) {
73-
return _urlToStyle[_canonicalize(url)];
74-
}
75-
76-
return null;
78+
return _urlToStyle[_canonicalize(url)];
7779
}
7880

79-
/** Get a list of all loaded stylesheet files by URL */
81+
/**
82+
* @deprecated Use styleSheetAdded and styleSheetRemoved events
83+
* Get a list of all loaded stylesheet files by URL
84+
*/
8085
function getStylesheetURLs() {
8186
var urls = [], url;
8287
for (url in _urlToStyle) {
@@ -87,37 +92,112 @@ define(function CSSAgent(require, exports, module) {
8792
return urls;
8893
}
8994

90-
/** Reload a CSS style sheet from a document
95+
/**
96+
* Reload a CSS style sheet from a document
9197
* @param {Document} document
98+
* @return {jQuery.Promise}
9299
*/
93100
function reloadCSSForDocument(doc) {
94101
var style = styleForURL(doc.url);
95102
console.assert(style, "Style Sheet for document not loaded: " + doc.url);
96-
Inspector.CSS.setStyleSheetText(style.styleSheetId, doc.getText());
103+
return Inspector.CSS.setStyleSheetText(style.styleSheetId, doc.getText());
97104
}
98105

99-
/** Empties a CSS style sheet given a document that has been deleted
106+
/**
107+
* Empties a CSS style sheet given a document that has been deleted
100108
* @param {Document} document
109+
* @return {jQuery.Promise}
101110
*/
102111
function clearCSSForDocument(doc) {
103112
var style = styleForURL(doc.url);
104113
console.assert(style, "Style Sheet for document not loaded: " + doc.url);
105-
Inspector.CSS.setStyleSheetText(style.styleSheetId, "");
114+
return Inspector.CSS.setStyleSheetText(style.styleSheetId, "");
115+
}
116+
117+
/**
118+
* @private
119+
* @param {jQuery.Event} event
120+
* @param {header: CSSStyleSheetHeader}
121+
*/
122+
function _styleSheetAdded(event, res) {
123+
var url = _canonicalize(res.header.sourceURL),
124+
existing = _urlToStyle[url];
125+
126+
// detect duplicates
127+
if (existing && existing.styleSheetId === res.header.styleSheetId) {
128+
return;
129+
}
130+
131+
_urlToStyle[url] = res.header;
132+
_styleSheetIdToUrl[res.header.styleSheetId] = url;
133+
134+
$(exports).triggerHandler("styleSheetAdded", [url, res.header]);
135+
}
136+
137+
/**
138+
* @private
139+
* @param {jQuery.Event} event
140+
* @param {styleSheetId: StyleSheetId}
141+
*/
142+
function _styleSheetRemoved(event, res) {
143+
var url = _styleSheetIdToUrl[res.styleSheetId],
144+
header = url && _urlToStyle[url];
145+
146+
if (url) {
147+
delete _urlToStyle[url];
148+
}
149+
150+
delete _styleSheetIdToUrl[res.styleSheetId];
151+
152+
$(exports).triggerHandler("styleSheetRemoved", [url, header]);
153+
}
154+
155+
/**
156+
* @private
157+
* Attempt to use deleted API CSS.getAllStyleSheets
158+
* @param {jQuery.Event} event
159+
* @param {frameId: Network.FrameId}
160+
*/
161+
function _onFrameStoppedLoading(event, res) {
162+
// Manually fire getAllStyleSheets since it will be removed from
163+
// Inspector.json in a future update
164+
Inspector.send("CSS", "getAllStyleSheets").done(function (res) {
165+
res.headers.forEach(function (header) {
166+
// _styleSheetAdded will ignore duplicates
167+
_styleSheetAdded(null, { header: header });
168+
});
169+
}).fail(function (err) {
170+
// Disable getAllStyleSheets if the first call fails
171+
_getAllStyleSheetsNotFound = (err.code === -32601);
172+
$(Inspector.Page).off("frameStoppedLoading.CSSAgent", _onFrameStoppedLoading);
173+
});
174+
}
175+
176+
/** Enable the domain */
177+
function enable() {
178+
return Inspector.CSS.enable();
106179
}
107180

108181
/** Initialize the agent */
109182
function load() {
110-
_load = new $.Deferred();
111-
$(Inspector.Page).on("loadEventFired.CSSAgent", _onLoadEventFired);
112-
return _load.promise();
183+
$(Inspector.Page).on("frameNavigated.CSSAgent", _onFrameNavigated);
184+
$(Inspector.CSS).on("styleSheetAdded.CSSAgent", _styleSheetAdded);
185+
$(Inspector.CSS).on("styleSheetRemoved.CSSAgent", _styleSheetRemoved);
186+
187+
// getAllStyleSheets was deleted beginning with Chrome 34
188+
if (!_getAllStyleSheetsNotFound) {
189+
$(Inspector.Page).on("frameStoppedLoading.CSSAgent", _onFrameStoppedLoading);
190+
}
113191
}
114192

115193
/** Clean up */
116194
function unload() {
117195
$(Inspector.Page).off(".CSSAgent");
196+
$(Inspector.CSS).off(".CSSAgent");
118197
}
119198

120199
// Export public functions
200+
exports.enable = enable;
121201
exports.styleForURL = styleForURL;
122202
exports.getStylesheetURLs = getStylesheetURLs;
123203
exports.reloadCSSForDocument = reloadCSSForDocument;

src/LiveDevelopment/Documents/CSSDocument.js

Lines changed: 41 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@
4848
define(function CSSDocumentModule(require, exports, module) {
4949
"use strict";
5050

51-
var CSSAgent = require("LiveDevelopment/Agents/CSSAgent"),
51+
var _ = require("thirdparty/lodash"),
52+
CSSAgent = require("LiveDevelopment/Agents/CSSAgent"),
5253
CSSUtils = require("language/CSSUtils"),
5354
EditorManager = require("editor/EditorManager"),
5455
HighlightAgent = require("LiveDevelopment/Agents/HighlightAgent"),
@@ -69,6 +70,7 @@ define(function CSSDocumentModule(require, exports, module) {
6970
this.doc.addRef();
7071
this.onChange = this.onChange.bind(this);
7172
this.onDeleted = this.onDeleted.bind(this);
73+
7274
$(this.doc).on("change.CSSDocument", this.onChange);
7375
$(this.doc).on("deleted.CSSDocument", this.onDeleted);
7476

@@ -81,33 +83,37 @@ define(function CSSDocumentModule(require, exports, module) {
8183
}
8284
};
8385

84-
/** Get the browser version of the StyleSheet object */
85-
CSSDocument.prototype.getStyleSheetFromBrowser = function getStyleSheetFromBrowser() {
86-
var deferred = new $.Deferred();
87-
88-
// WebInspector Command: CSS.getStyleSheet
89-
Inspector.CSS.getStyleSheet(this.styleSheet.styleSheetId, function callback(res) {
90-
// res = {styleSheet}
91-
if (res.styleSheet) {
92-
deferred.resolve(res.styleSheet);
93-
} else {
94-
deferred.reject();
95-
}
96-
});
86+
/**
87+
* @private
88+
* Get the CSSStyleSheetHeader for this document
89+
*/
90+
CSSDocument.prototype._getStyleSheetHeader = function () {
91+
return CSSAgent.styleForURL(this.doc.url);
92+
};
9793

98-
return deferred.promise();
94+
/**
95+
* @deprecated
96+
* CSSStyleSheetBody was removed in protocol 1.1. This method is unused in Brackets 36.
97+
* Get the browser version of the StyleSheet object
98+
* @return {jQuery.promise}
99+
*/
100+
CSSDocument.prototype.getStyleSheetFromBrowser = function getStyleSheetFromBrowser() {
101+
return new $.Deferred().reject().promise();
99102
};
100103

101-
/** Get the browser version of the source */
104+
/**
105+
* Get the browser version of the source
106+
* @return {jQuery.promise} Promise resolved with the text content of this CSS document
107+
*/
102108
CSSDocument.prototype.getSourceFromBrowser = function getSourceFromBrowser() {
103-
var deferred = new $.Deferred();
104-
105-
this.getStyleSheetFromBrowser().done(function onDone(styleSheet) {
106-
deferred.resolve(styleSheet.text);
107-
}).fail(function onFail() {
108-
deferred.reject();
109-
});
110-
109+
var deferred = new $.Deferred(),
110+
styleSheetId = this._getStyleSheetHeader().styleSheetId,
111+
inspectorPromise = Inspector.CSS.getStyleSheetText(styleSheetId);
112+
113+
inspectorPromise.then(function (res) {
114+
deferred.resolve(res.text);
115+
}, deferred.reject);
116+
111117
return deferred.promise();
112118
};
113119

@@ -118,17 +124,16 @@ define(function CSSDocumentModule(require, exports, module) {
118124
this.doc.releaseRef();
119125
this.detachFromEditor();
120126
};
121-
127+
122128
/**
123-
* Force the browser to update if the file is dirty
129+
* @private
130+
* Update the style sheet text content and redraw highlights
124131
*/
125132
CSSDocument.prototype._updateBrowser = function () {
126-
// get the style sheet
127-
this.styleSheet = CSSAgent.styleForURL(this.doc.url);
133+
var reloadPromise = CSSAgent.reloadCSSForDocument(this.doc);
128134

129-
// If the CSS document is dirty, push the changes into the browser now
130-
if (this.doc.isDirty) {
131-
CSSAgent.reloadCSSForDocument(this.doc);
135+
if (Inspector.config.highlight) {
136+
reloadPromise.done(HighlightAgent.redraw);
132137
}
133138
};
134139

@@ -200,11 +205,7 @@ define(function CSSDocumentModule(require, exports, module) {
200205

201206
/** Triggered whenever the Document is edited */
202207
CSSDocument.prototype.onChange = function onChange(event, editor, change) {
203-
// brute force: update the CSS
204-
CSSAgent.reloadCSSForDocument(this.doc);
205-
if (Inspector.config.highlight) {
206-
HighlightAgent.redraw();
207-
}
208+
this._updateBrowser();
208209
};
209210

210211
/** Triggered if the Document's file is deleted */
@@ -241,11 +242,13 @@ define(function CSSDocumentModule(require, exports, module) {
241242
// WebInspector Command: CSS.getMatchedStylesForNode
242243
Inspector.CSS.getMatchedStylesForNode(node.nodeId, function onGetMatchesStyles(res) {
243244
// res = {matchedCSSRules, pseudoElements, inherited}
244-
var codeMirror = this.editor._codeMirror;
245+
var codeMirror = this.editor._codeMirror,
246+
styleSheetId = this._getStyleSheetHeader().styleSheetId;
247+
245248
var i, rule, from, to;
246249
for (i in res.matchedCSSRules) {
247250
rule = res.matchedCSSRules[i];
248-
if (rule.ruleId && rule.ruleId.styleSheetId === this.styleSheet.styleSheetId) {
251+
if (rule.ruleId && rule.ruleId.styleSheetId === styleSheetId) {
249252
from = codeMirror.posFromIndex(rule.selectorRange.start);
250253
to = codeMirror.posFromIndex(rule.style.range.end);
251254
this._highlight.push(codeMirror.markText(from, to, { className: "highlight" }));

0 commit comments

Comments
 (0)