Uncaught DOMException: не удалось прочитать свойство "rules" из "CSSStyleSheet"
В редакторе App Lab Code.org мы недавно начали видеть эту ошибку в 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, и, похоже, мы не можем воспроизвести проблему в окне инкогнито.
Какова основная причина этой ошибки?
2 ответа
Это была хорошая история и новая "проблема" для веб-разработчиков, поэтому мне просто хотелось поделиться:
В Chrome 64.0.3282.0 (выпущен в январе 2018 года, полный список изменений) внесены изменения в правила безопасности для таблиц стилей. Меня раздражает, что я не могу найти это изменение в любом журнале изменений, менее подробном, чем полный список коммитов.
Коммит a4ebe08 в Chromium описан:
Обновить поведение CSSStyleSheet, чтобы оно соответствовало спецификации источника безопасности
Спецификация здесь: https://www.w3.org/TR/cssom-1/
Обновлено: следующие методы теперь выдают ошибку SecurityError, если таблица стилей недоступна:
- cssRules () / rules ()
- insertRule ()
- deleteRule ()
Этот коммит исправляет ошибку Security: Несогласованная реализация CORS относительно CSS и элемента link. Связанная спецификация W3C подробно описывает, где использование объектной модели CSS требует доступа того же источника.
Все это говорит о том, почему эта проблема обнаруживается в App Lab? Мы не должны испытывать никаких проблем с CORS, потому что мы загружаем таблицы стилей только из нашего собственного источника:
В итоге намекнули, что мы не можем воспроизвести эту проблему на закрытой вкладке. Мы начали смотреть на расширения Chrome и поняли, что у некоторых затронутых пользователей было включено расширение Loom Video Recorder, которое, похоже, внедряет свой собственный CSS в страницу. Поскольку наша (наивная) функция выполняла итерацию по всем загруженным таблицам стилей, она пыталась получить доступ к этой таблице стилей, введенной расширением, и, таким образом, вызвала ошибку CORS.
Тем не менее, есть еще некоторые открытые вопросы и дебаты вокруг этого изменения в Chrome:
- В этом комментарии к исходной ошибке безопасности сообщается, что единственный способ определить, что таблица стилей недоступна из JavaScript, - это
try/catch
, - Ошибка Chromium, открытая 23 января ( document.styleSheets.cssRules является нулевой, даже с Access-Control-Allow-Origin: *), предполагает, что может быть проблема реализации с новым правилом безопасности, которое нарушает определенные обходные пути.
- Реализуемая спецификация кажется довольно стабильной, но она все еще имеет статус "Рабочий проект", так что кто знает, где она появится и что будут реализовывать другие браузеры.
Чтобы решить нашу проблему, мы просто оторвали всю функцию. Мы больше не поддерживаем 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 {
var classes = stylesheets[s].rules || stylesheets[s].cssRules;
} catch (e) {
console.warn("Can't read the css rules of: " + stylesheets[s].href, e);
continue
}
Была эта проблема и ломала мне голову, и это, казалось, работало... Удачи!
Для меня работает, чтобы переместить ссылку css href из заголовка в конец тега тела.
<link rel="stylesheet" href=".....">
</body>