未捕获的DOMException:无法从'CSSStyleSheet'读取'rules'属性

时间:2018-03-07 21:03:49

标签: javascript css google-chrome cors cssom

在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版本和平台上 - 我们似乎无法在隐身窗口中重现该问题。

此错误的根本原因是什么?

3 个答案:

答案 0 :(得分:10)

对于网页开发者来说,这是一个很好的故事和新的“问题”,所以我只需要分享:

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()
  •   

此提交是对错误Security: Inconsistent CORS implementation regarding CSS and the link element.的修复。链接的W3C规范详细描述了CSS对象模型的使用需要同源访问。

所有这一切,为什么这个问题出现在App Lab中?我们不应该遇到任何CORS问题,因为我们只从我们自己的来源加载样式表:

Chrome network tab showing all CSS requested from the affected page

最后的线索是我们无法在私人标签中重现此问题。我们开始查看Chrome扩展程序并意识到某些受影响的用户已启用Loom Video Recorder扩展程序,这似乎会将自己的CSS注入到页面中。由于我们的(天真)函数正在迭代所有加载的样式表,因此它试图访问由扩展注入的样式表,从而导致CORS错误。

也就是说,Chrome中存在一些未解决的问题和争议:

    关于原始安全漏洞的
  • This comment抱怨说现在检测到无法从JavaScript访问样式表的唯一方法是使用try/catch
  • 1月23日开放的Chromium bug(document.styleSheets.cssRules is null even with Access-Control-Allow-Origin: *)表明新安全规则可能存在实施问题,导致某些变通办法出现问题。
  • 正在实施的规范似乎相当稳定,但它仍然具有“工作草案”状态,因此谁知道它将落在哪里以及其他浏览器将实现什么。

To fix our problem, we just tore out the entire function.我们不再支持IE9了,我们知道所有支持的浏览器都能正确处理媒体查询。

相关(但不完全重复)的问题:

答案 1 :(得分:0)

对我来说,它是将css链接href从标题移动到body标签结尾。

<link rel="stylesheet" href=".....">
</body>

答案 2 :(得分:-1)

如果其他人遇到与跨域资源共享(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 {
  var classes = stylesheets[s].rules || stylesheets[s].cssRules;
} catch (e) {
  console.warn("Can't read the css rules of: " + stylesheets[s].href, e);
  continue
}

遇到了这个问题,让我不知所措,这似乎奏效了……祝您好运!