在Code.org的App Lab编辑器中,我们最近开始在Chrome 64中看到此错误:
Uncaught DOMException: Failed to read the 'rules' property from 'CSSStyleSheet'
此函数抛出此错误,旨在检测浏览器是否正在使用CSS媒体查询,包括styleSheets[i].cssRules
。
/**
* IE9 throws an exception when trying to access the media field of a stylesheet
*/
export function browserSupportsCssMedia() {
var styleSheets = document.styleSheets;
for (var i = 0; i < styleSheets.length; i++) {
var rules = styleSheets[i].cssRules || styleSheets[i].rules;
try {
if (rules.length > 0) {
// see if we can access media
rules[0].media;
}
} catch (e) {
return false;
}
}
return true;
}
在Windows,OSX,Ubuntu和ChromeOS上已经出现了这个问题。在Chrome版本64.0.3282.167和64.0.3282.186上。但是,我们也看到这个问题不会发生在完全相同的Chrome版本和平台上 - 而且我们似乎无法在隐身窗口中重现此问题。
这个错误的根本原因是什么?
对于Web开发人员来说,这是一个很好的故事和新的“问题”,所以我只需要分享:
Chrome 64.0.3282。0(2018年1月发布,full change list)引入了对样式表安全规则的更改。我很恼火,因为在完整提交列表中没有详细记录的任何更改日志中我找不到此更改。
在Chromium中提交a4ebe08描述:
更新CSSStyleSheet的行为以匹配安全性来源的规范
规格在这里:https://www.w3.org/TR/cssom-1/#the-cssstylesheet-interface
更新:如果样式表不可访问,以下方法现在抛出SecurityError:
- cssRules()/ rules()
- insertRule()
- deleteRule()
此提交是对bug Security: Inconsistent CORS implementation regarding CSS and the link element.的修复。链接的W3C规范详细描述了CSS对象模型的使用需要同源访问。
所有这一切,为什么这个问题出现在App Lab中?我们不应该遇到任何CORS问题,因为我们只从我们自己的来源加载样式表:
最后的线索是我们无法在私人标签中重现此问题。我们开始关注Chrome扩展,并意识到一些受影响的用户启用了Loom Video Recorder扩展,这似乎将自己的CSS注入页面。由于我们的(天真)函数正在迭代所有加载的样式表,因此它试图访问由扩展注入的样式表,从而导致CORS错误。
也就是说,Chrome中的这一变化仍有一些悬而未决的问题和争论:
try/catch
。To fix our problem, we just tore out the entire function.我们不再支持IE9了,我们知道所有支持的浏览器都能正确处理媒体查询。
相关(但不完全重复)的问题:
如果其他人有与跨源资源共享(CORS)策略相关的问题,请在此处讨论:https://github.com/Modernizr/Modernizr/issues/2296
您必须使用本地主机进行测试:https://developer.mozilla.org/en-US/docs/Learn/Common_questions/set_up_a_local_testing_server
以下是“try / catch”方法的解决方法:
try {
var classes = stylesheets[s].rules || stylesheets[s].cssRules;
} catch (e) {
console.warn("Can't read the css rules of: " + stylesheets[s].href, e);
continue
}
有这个问题,并在绞尽脑汁,这似乎工作......祝你好运!