-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Fix Live CSS with an iframe element #8144
Changes from 9 commits
b496f08
db16092
7546767
f99d852
0b39d2e
d81e380
a0fabf5
43e9ce6
f3206d3
1893696
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,19 +37,15 @@ define(function CSSAgent(require, exports, module) { | |
|
||
require("thirdparty/path-utils/path-utils.min"); | ||
|
||
var _ = require("thirdparty/lodash"); | ||
|
||
var Inspector = require("LiveDevelopment/Inspector/Inspector"); | ||
|
||
/** | ||
* Stylesheet urls | ||
* Stylesheet details | ||
* @type {Object.<string, CSS.CSSStyleSheetHeader>} | ||
*/ | ||
var _urlToStyle = {}; | ||
|
||
/** | ||
* Map of stylesheet ids to urls | ||
* @type {Object.<string, string>} | ||
*/ | ||
var _styleSheetIdToUrl; | ||
var _styleSheetDetails = {}; | ||
|
||
/** | ||
* Is getAllStyleSheets() API defined? - This is undefined until we test for API | ||
|
@@ -73,18 +69,26 @@ define(function CSSAgent(require, exports, module) { | |
* @param {frame: Frame} res | ||
*/ | ||
function _onFrameNavigated(event, res) { | ||
// Clear maps when navigating to a new page | ||
_urlToStyle = {}; | ||
_styleSheetIdToUrl = {}; | ||
// Clear maps when navigating to a new page, but not if an iframe was loaded | ||
if (!res.frame.parentId) { | ||
_styleSheetDetails = {}; | ||
} | ||
} | ||
|
||
/** | ||
* Get a style sheet for a url | ||
* @param {string} url | ||
* @return {CSS.CSSStyleSheetHeader} | ||
* @return {Array.<CSSStyleSheetHeader>} | ||
*/ | ||
function styleForURL(url) { | ||
return _urlToStyle[_canonicalize(url)]; | ||
var styleSheetId, styles = {}; | ||
url = _canonicalize(url); | ||
for (styleSheetId in _styleSheetDetails) { | ||
if (_styleSheetDetails[styleSheetId].canonicalizedURL === url) { | ||
styles[styleSheetId] = _styleSheetDetails[styleSheetId]; | ||
} | ||
} | ||
return styles; | ||
} | ||
|
||
/** | ||
|
@@ -93,24 +97,36 @@ define(function CSSAgent(require, exports, module) { | |
* @deprecated | ||
*/ | ||
function getStylesheetURLs() { | ||
var urls = [], url; | ||
for (url in _urlToStyle) { | ||
if (_urlToStyle.hasOwnProperty(url)) { | ||
urls.push(url); | ||
} | ||
var styleSheetId, urls = []; | ||
for (styleSheetId in _styleSheetDetails) { | ||
urls[_styleSheetDetails[styleSheetId].canonicalizedURL] = true; | ||
} | ||
return urls; | ||
return _.keys(urls); | ||
} | ||
|
||
/** | ||
* Reload a CSS style sheet from a document | ||
* @param {Document} document | ||
* @param {string=} newContent new content of every stylesheet. Defaults to doc.getText() if omitted | ||
* @return {jQuery.Promise} | ||
*/ | ||
function reloadCSSForDocument(doc) { | ||
var style = styleForURL(doc.url); | ||
console.assert(style, "Style Sheet for document not loaded: " + doc.url); | ||
return Inspector.CSS.setStyleSheetText(style.styleSheetId, doc.getText()); | ||
function reloadCSSForDocument(doc, newContent) { | ||
var styles = styleForURL(doc.url), | ||
styleSheetId, | ||
deferreds = []; | ||
|
||
if (newContent === undefined) { | ||
newContent = doc.getText(); | ||
} | ||
for (styleSheetId in styles) { | ||
deferreds.push(Inspector.CSS.setStyleSheetText(styles[styleSheetId].styleSheetId, newContent)); | ||
} | ||
if (!deferreds.length) { | ||
console.error("Style Sheet for document not loaded: " + doc.url); | ||
return new $.Deferred().reject().promise(); | ||
} | ||
// return master deferred | ||
return $.when.apply($, deferreds); | ||
} | ||
|
||
/** | ||
|
@@ -119,9 +135,7 @@ define(function CSSAgent(require, exports, module) { | |
* @return {jQuery.Promise} | ||
*/ | ||
function clearCSSForDocument(doc) { | ||
var style = styleForURL(doc.url); | ||
console.assert(style, "Style Sheet for document not loaded: " + doc.url); | ||
return Inspector.CSS.setStyleSheetText(style.styleSheetId, ""); | ||
return reloadCSSForDocument(doc, ""); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice refactoring! |
||
} | ||
|
||
/** | ||
|
@@ -130,16 +144,21 @@ define(function CSSAgent(require, exports, module) { | |
* @param {header: CSSStyleSheetHeader} | ||
*/ | ||
function _styleSheetAdded(event, res) { | ||
var url = _canonicalize(res.header.sourceURL), | ||
existing = _urlToStyle[url]; | ||
var url = _canonicalize(res.header.sourceURL), | ||
existing = styleForURL(res.header.sourceURL), | ||
styleSheetId = res.header.styleSheetId, | ||
duplicate; | ||
|
||
// detect duplicates | ||
if (existing && existing.styleSheetId === res.header.styleSheetId) { | ||
duplicate = _.some(existing, function (styleSheet) { | ||
return styleSheet && styleSheet.styleSheetId === styleSheetId; | ||
}); | ||
if (duplicate) { | ||
return; | ||
} | ||
|
||
_urlToStyle[url] = res.header; | ||
_styleSheetIdToUrl[res.header.styleSheetId] = url; | ||
_styleSheetDetails[styleSheetId] = res.header; | ||
_styleSheetDetails[styleSheetId].canonicalizedURL = url; // canonicalized URL | ||
|
||
$(exports).triggerHandler("styleSheetAdded", [url, res.header]); | ||
} | ||
|
@@ -150,16 +169,11 @@ define(function CSSAgent(require, exports, module) { | |
* @param {styleSheetId: StyleSheetId} | ||
*/ | ||
function _styleSheetRemoved(event, res) { | ||
var url = _styleSheetIdToUrl[res.styleSheetId], | ||
header = url && _urlToStyle[url]; | ||
|
||
if (url) { | ||
delete _urlToStyle[url]; | ||
} | ||
var header = _styleSheetDetails[res.styleSheetId]; | ||
|
||
delete _styleSheetIdToUrl[res.styleSheetId]; | ||
delete _styleSheetDetails[res.styleSheetId]; | ||
|
||
$(exports).triggerHandler("styleSheetRemoved", [url, header]); | ||
$(exports).triggerHandler("styleSheetRemoved", [header.canonicalizedURL, header]); | ||
} | ||
|
||
/** | ||
|
@@ -233,4 +247,4 @@ define(function CSSAgent(require, exports, module) { | |
exports.clearCSSForDocument = clearCSSForDocument; | ||
exports.load = load; | ||
exports.unload = unload; | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -108,8 +108,18 @@ define(function CSSDocumentModule(require, exports, module) { | |
* @return {jQuery.promise} Promise resolved with the text content of this CSS document | ||
*/ | ||
CSSDocument.prototype.getSourceFromBrowser = function getSourceFromBrowser() { | ||
function getOnlyValue(obj) { | ||
var key; | ||
for (key in obj) { | ||
if (_.has(obj, key)) { | ||
return obj[key]; | ||
} | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't noticed this before, but this function should explicitly |
||
|
||
var deferred = new $.Deferred(), | ||
styleSheetId = this._getStyleSheetHeader().styleSheetId, | ||
styleSheetHeader = this._getStyleSheetHeader(), | ||
styleSheetId = getOnlyValue(styleSheetHeader).styleSheetId, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: I am getting the following exceptions just launching Live Preview in this recipe:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't see that error, but it seems like it's a race condition. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure if that error is related to this code, but I still think this potential exception should be prevented. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Was it an intermittent one or do you still see it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm no longer seeing the error. |
||
inspectorPromise = Inspector.CSS.getStyleSheetText(styleSheetId); | ||
|
||
inspectorPromise.then(function (res) { | ||
|
@@ -252,12 +262,12 @@ define(function CSSDocumentModule(require, exports, module) { | |
Inspector.CSS.getMatchedStylesForNode(node.nodeId, function onGetMatchesStyles(res) { | ||
// res = {matchedCSSRules, pseudoElements, inherited} | ||
var codeMirror = this.editor._codeMirror, | ||
styleSheetId = this._getStyleSheetHeader().styleSheetId; | ||
styleSheetIds = this._getStyleSheetHeader(); | ||
|
||
var i, rule, from, to; | ||
for (i in res.matchedCSSRules) { | ||
rule = res.matchedCSSRules[i]; | ||
if (rule.ruleId && rule.ruleId.styleSheetId === styleSheetId) { | ||
if (rule.ruleId && styleSheetIds[rule.ruleId.styleSheetId]) { | ||
from = codeMirror.posFromIndex(rule.selectorRange.start); | ||
to = codeMirror.posFromIndex(rule.style.range.end); | ||
this._highlight.push(codeMirror.markText(from, to, { className: "highlight" })); | ||
|
@@ -268,4 +278,4 @@ define(function CSSDocumentModule(require, exports, module) { | |
|
||
// Export the class | ||
module.exports = CSSDocument; | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#testId { | ||
font-size: 20px; | ||
} | ||
|
||
.testClass { | ||
background-color:rgba(102,102,204,.5); | ||
color:rgba(255,255,255,1); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<!doctype html> | ||
<html> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<title>Simple Test</title> | ||
<link rel="stylesheet" href="simpleShared.css"> | ||
<link rel="stylesheet" href="simple1.css"> | ||
</head> | ||
|
||
<body> | ||
<p id="testId" class="testClass">iframes are cool.</p> | ||
<iframe src="iframe.html"></iframe> | ||
</body> | ||
</html> |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this ever return more than 1 stylesheet for a url? If so, what's the use case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's the big problem we had.
Let's say you've got this code:
In that case, you've got the exact same stylesheet used in two different documents on one page, and what this means is that the browser/inspector has two different stylesheet objects with the same URL.