Skip to content
This repository was archived by the owner on Sep 6, 2021. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
04b015e
use styleSheetAdded and styleSheetRemoved to replace deleted getAllSt…
jasonsanjose Feb 26, 2014
e2ef6eb
fix related doc ref count errors
jasonsanjose Feb 26, 2014
0905ca4
fallback to getAllStyleSheets if available
jasonsanjose Feb 26, 2014
02e2b10
add error handling when getAllStyleSheets is not found in inspector p…
jasonsanjose Feb 26, 2014
ab40ce0
do not change live dev status for inspector errors
jasonsanjose Feb 26, 2014
d2a8a82
account for styleSheetId changes after a CSSDocument reloads
jasonsanjose Feb 27, 2014
87bb739
remove styleSheetRemoved handler. handle weird chrome behavior where …
jasonsanjose Feb 27, 2014
24d3cf2
fix jslint error. Fix getSourceFromBrowser response. Remove debounce …
jasonsanjose Feb 28, 2014
8af9aee
fix failing unit tests. restore CSSDocument initial call to _updateBr…
jasonsanjose Feb 28, 2014
24a3969
Merge remote-tracking branch 'origin/master' into jasonsanjose/issue-…
jasonsanjose Feb 28, 2014
cbe4b09
remove extraneous reject for _openDeferred
jasonsanjose Feb 28, 2014
190f437
Ignore LiveDevelopment.close() if not active
jasonsanjose Feb 28, 2014
d2b33f5
Merge remote-tracking branch 'origin/master' into jasonsanjose/issue-…
redmunds Feb 28, 2014
4ac3e07
Merge branch 'jasonsanjose/issue-6830' of https://github.com/adobe/br…
redmunds Feb 28, 2014
00dde93
code review comments
jasonsanjose Mar 4, 2014
85b5d8c
Merge branch 'jasonsanjose/issue-6830' of https://github.com/adobe/br…
jasonsanjose Mar 4, 2014
d1a6752
Merge remote-tracking branch 'origin/master' into jasonsanjose/issue-…
jasonsanjose Mar 4, 2014
3cee9fe
fix async call to getLiveDocForPath
jasonsanjose Mar 4, 2014
ac80eca
update unit test spy for API change
jasonsanjose Mar 5, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 110 additions & 30 deletions src/LiveDevelopment/Agents/CSSAgent.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,25 @@
/**
* CSSAgent keeps track of loaded style sheets and allows reloading them
* from a {Document}.
*
* CSSAgent dispatches styleSheetAdded and styleSheetRemoved events, passing
* the URL for the added/removed style sheet.
*/

define(function CSSAgent(require, exports, module) {
"use strict";

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

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

var _load; // {$.Deferred} load promise
var _urlToStyle; // {url -> loaded} style definition
/** @type {Object.<string, CSS.CSSStyleSheetHeader>} */
var _urlToStyle = {};

/** @type {Object.<string, string>} */
var _styleSheetIdToUrl;

/** @type {boolean} */
var _getAllStyleSheetsNotFound = false;

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

// WebInspector Event: Page.loadEventFired
function _onLoadEventFired(event, res) {
// res = {timestamp}
/**
* @private
* WebInspector Event: Page.frameNavigated
* @param {jQuery.Event} event
* @param {frame: Frame} res
*/
function _onFrameNavigated(event, res) {
// Clear maps when navigating to a new page
_urlToStyle = {};
Inspector.CSS.enable().done(function () {
Inspector.CSS.getAllStyleSheets(function onGetAllStyleSheets(res) {
var i, header;
for (i in res.headers) {
header = res.headers[i];
_urlToStyle[_canonicalize(header.sourceURL)] = header;
}
_load.resolve();
});
});
_styleSheetIdToUrl = {};
}

/** Get a style sheet for a url
/**
* Get a style sheet for a url
* @param {string} url
* @return {CSS.CSSStyleSheetHeader}
*/
function styleForURL(url) {
if (_urlToStyle) {
return _urlToStyle[_canonicalize(url)];
}

return null;
return _urlToStyle[_canonicalize(url)];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since code no longer checks if (_urlToStyle) then _urlToStyle should be initialized to _urlToStyle = {} on line 43 to be safe. Same for _styleSheetIdToUrl.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

}

/** Get a list of all loaded stylesheet files by URL */
/**
* @deprecated Use styleSheetAdded and styleSheetRemoved events
* Get a list of all loaded stylesheet files by URL
*/
function getStylesheetURLs() {
var urls = [], url;
for (url in _urlToStyle) {
Expand All @@ -87,37 +92,112 @@ define(function CSSAgent(require, exports, module) {
return urls;
}

/** Reload a CSS style sheet from a document
/**
* Reload a CSS style sheet from a document
* @param {Document} document
* @return {jQuery.Promise}
*/
function reloadCSSForDocument(doc) {
var style = styleForURL(doc.url);
console.assert(style, "Style Sheet for document not loaded: " + doc.url);
Inspector.CSS.setStyleSheetText(style.styleSheetId, doc.getText());
return Inspector.CSS.setStyleSheetText(style.styleSheetId, doc.getText());
}

/** Empties a CSS style sheet given a document that has been deleted
/**
* Empties a CSS style sheet given a document that has been deleted
* @param {Document} document
* @return {jQuery.Promise}
*/
function clearCSSForDocument(doc) {
var style = styleForURL(doc.url);
console.assert(style, "Style Sheet for document not loaded: " + doc.url);
Inspector.CSS.setStyleSheetText(style.styleSheetId, "");
return Inspector.CSS.setStyleSheetText(style.styleSheetId, "");
}

/**
* @private
* @param {jQuery.Event} event
* @param {header: CSSStyleSheetHeader}
*/
function _styleSheetAdded(event, res) {
var url = _canonicalize(res.header.sourceURL),
existing = _urlToStyle[url];

// detect duplicates
if (existing && existing.styleSheetId === res.header.styleSheetId) {
return;
}

_urlToStyle[url] = res.header;
_styleSheetIdToUrl[res.header.styleSheetId] = url;

$(exports).triggerHandler("styleSheetAdded", [url, res.header]);
}

/**
* @private
* @param {jQuery.Event} event
* @param {styleSheetId: StyleSheetId}
*/
function _styleSheetRemoved(event, res) {
var url = _styleSheetIdToUrl[res.styleSheetId],
header = url && _urlToStyle[url];

if (url) {
delete _urlToStyle[url];
}

delete _styleSheetIdToUrl[res.styleSheetId];

$(exports).triggerHandler("styleSheetRemoved", [url, header]);
}

/**
* @private
* Attempt to use deleted API CSS.getAllStyleSheets
* @param {jQuery.Event} event
* @param {frameId: Network.FrameId}
*/
function _onFrameStoppedLoading(event, res) {
// Manually fire getAllStyleSheets since it will be removed from
// Inspector.json in a future update
Inspector.send("CSS", "getAllStyleSheets").done(function (res) {
res.headers.forEach(function (header) {
// _styleSheetAdded will ignore duplicates
_styleSheetAdded(null, { header: header });
});
}).fail(function (err) {
// Disable getAllStyleSheets if the first call fails
_getAllStyleSheetsNotFound = (err.code === -32601);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe write to console.log if it's some other error code?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do this already in the _onError handling in LiveDevelopment.

$(Inspector.Page).off("frameStoppedLoading.CSSAgent", _onFrameStoppedLoading);
});
}

/** Enable the domain */
function enable() {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Allow enable during LiveDevelopment _onInterstitialPageLoad(). The old behavior would wait all the way until loadEventFired to enable the CSS domain. This also allows loadAgents() to complete faster since we no longer wait for the sequence of (1) loadEventFired, (2) enable and (3) getAllStylesheets.

return Inspector.CSS.enable();
}

/** Initialize the agent */
function load() {
_load = new $.Deferred();
$(Inspector.Page).on("loadEventFired.CSSAgent", _onLoadEventFired);
return _load.promise();
$(Inspector.Page).on("frameNavigated.CSSAgent", _onFrameNavigated);
$(Inspector.CSS).on("styleSheetAdded.CSSAgent", _styleSheetAdded);
$(Inspector.CSS).on("styleSheetRemoved.CSSAgent", _styleSheetRemoved);

// getAllStyleSheets was deleted beginning with Chrome 34
if (!_getAllStyleSheetsNotFound) {
$(Inspector.Page).on("frameStoppedLoading.CSSAgent", _onFrameStoppedLoading);
}
}

/** Clean up */
function unload() {
$(Inspector.Page).off(".CSSAgent");
$(Inspector.CSS).off(".CSSAgent");
}

// Export public functions
exports.enable = enable;
exports.styleForURL = styleForURL;
exports.getStylesheetURLs = getStylesheetURLs;
exports.reloadCSSForDocument = reloadCSSForDocument;
Expand Down
79 changes: 41 additions & 38 deletions src/LiveDevelopment/Documents/CSSDocument.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@
define(function CSSDocumentModule(require, exports, module) {
"use strict";

var CSSAgent = require("LiveDevelopment/Agents/CSSAgent"),
var _ = require("thirdparty/lodash"),
CSSAgent = require("LiveDevelopment/Agents/CSSAgent"),
CSSUtils = require("language/CSSUtils"),
EditorManager = require("editor/EditorManager"),
HighlightAgent = require("LiveDevelopment/Agents/HighlightAgent"),
Expand All @@ -69,6 +70,7 @@ define(function CSSDocumentModule(require, exports, module) {
this.doc.addRef();
this.onChange = this.onChange.bind(this);
this.onDeleted = this.onDeleted.bind(this);

$(this.doc).on("change.CSSDocument", this.onChange);
$(this.doc).on("deleted.CSSDocument", this.onDeleted);

Expand All @@ -81,33 +83,37 @@ define(function CSSDocumentModule(require, exports, module) {
}
};

/** Get the browser version of the StyleSheet object */
CSSDocument.prototype.getStyleSheetFromBrowser = function getStyleSheetFromBrowser() {
var deferred = new $.Deferred();

// WebInspector Command: CSS.getStyleSheet
Inspector.CSS.getStyleSheet(this.styleSheet.styleSheetId, function callback(res) {
// res = {styleSheet}
if (res.styleSheet) {
deferred.resolve(res.styleSheet);
} else {
deferred.reject();
}
});
/**
* @private
* Get the CSSStyleSheetHeader for this document
*/
CSSDocument.prototype._getStyleSheetHeader = function () {
return CSSAgent.styleForURL(this.doc.url);
};

return deferred.promise();
/**
* @deprecated
* CSSStyleSheetBody was removed in protocol 1.1. This method is unused in Brackets 36.
* Get the browser version of the StyleSheet object
* @return {jQuery.promise}
*/
CSSDocument.prototype.getStyleSheetFromBrowser = function getStyleSheetFromBrowser() {
return new $.Deferred().reject().promise();
};

/** Get the browser version of the source */
/**
* Get the browser version of the source
* @return {jQuery.promise} Promise resolved with the text content of this CSS document
*/
CSSDocument.prototype.getSourceFromBrowser = function getSourceFromBrowser() {
var deferred = new $.Deferred();

this.getStyleSheetFromBrowser().done(function onDone(styleSheet) {
deferred.resolve(styleSheet.text);
}).fail(function onFail() {
deferred.reject();
});

var deferred = new $.Deferred(),
styleSheetId = this._getStyleSheetHeader().styleSheetId,
inspectorPromise = Inspector.CSS.getStyleSheetText(styleSheetId);

inspectorPromise.then(function (res) {
deferred.resolve(res.text);
}, deferred.reject);
return deferred.promise();
};

Expand All @@ -118,17 +124,16 @@ define(function CSSDocumentModule(require, exports, module) {
this.doc.releaseRef();
this.detachFromEditor();
};

/**
* Force the browser to update if the file is dirty
* @private
* Update the style sheet text content and redraw highlights
*/
CSSDocument.prototype._updateBrowser = function () {
// get the style sheet
this.styleSheet = CSSAgent.styleForURL(this.doc.url);
var reloadPromise = CSSAgent.reloadCSSForDocument(this.doc);

// If the CSS document is dirty, push the changes into the browser now
if (this.doc.isDirty) {
CSSAgent.reloadCSSForDocument(this.doc);
if (Inspector.config.highlight) {
reloadPromise.done(HighlightAgent.redraw);
}
};

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

/** Triggered whenever the Document is edited */
CSSDocument.prototype.onChange = function onChange(event, editor, change) {
// brute force: update the CSS
CSSAgent.reloadCSSForDocument(this.doc);
if (Inspector.config.highlight) {
HighlightAgent.redraw();
}
this._updateBrowser();
};

/** Triggered if the Document's file is deleted */
Expand Down Expand Up @@ -241,11 +242,13 @@ define(function CSSDocumentModule(require, exports, module) {
// WebInspector Command: CSS.getMatchedStylesForNode
Inspector.CSS.getMatchedStylesForNode(node.nodeId, function onGetMatchesStyles(res) {
// res = {matchedCSSRules, pseudoElements, inherited}
var codeMirror = this.editor._codeMirror;
var codeMirror = this.editor._codeMirror,
styleSheetId = this._getStyleSheetHeader().styleSheetId;

var i, rule, from, to;
for (i in res.matchedCSSRules) {
rule = res.matchedCSSRules[i];
if (rule.ruleId && rule.ruleId.styleSheetId === this.styleSheet.styleSheetId) {
if (rule.ruleId && rule.ruleId.styleSheetId === styleSheetId) {
from = codeMirror.posFromIndex(rule.selectorRange.start);
to = codeMirror.posFromIndex(rule.style.range.end);
this._highlight.push(codeMirror.markText(from, to, { className: "highlight" }));
Expand Down
Loading