v158 · cssom · migration
The null check your traversal needs
ChromeStatus's own compat note for this feature: “Existing Chromium code may assume that styleSheet is non-null… Such code may need a null check.” Here is that assumption as running code — a little stylesheet auditor that counts rules across an import tree, written two ways, run against a fixture whose imports include one that loads, one that fails, and one whose supports() condition is false. Whatever happens, happens live in your browser.
On pre-158 Chromium the legacy auditor usually appears to work — the failed import hands it a phantom empty sheet to count. From Chrome 158 (CSSImportRuleStyleSheetNullable, no flag on earlier builds) the same chain throws a real TypeError. That inversion — code that breaks only once the browser becomes more spec-correct — is exactly why the null-safe form is worth adopting before 158 reaches your users.
The fixture
Pressing either button (re)builds this import tree in a live style element, waits a beat for fetches to settle, then runs the chosen auditor over it:
@import url("../sheets/audit-fixture.css"); /* loads; itself imports applied.css */
@import url("../sheets/not-css.txt"); /* HTTP 200 but text/plain: load fails */
@import url("../sheets/applied.css") supports((display: pancake)); /* never fetched */
Legacy (pre-158 code)
function countRules(sheet) {
let n = sheet.cssRules.length;
for (const rule of sheet.cssRules) {
if (rule instanceof CSSImportRule) {
// assumes styleSheet is never null
n += countRules(rule.styleSheet);
}
}
return n;
}
Not run yet.
Null-safe (158-ready)
function countRules(sheet) {
let n = sheet.cssRules.length;
for (const rule of sheet.cssRules) {
if (rule instanceof CSSImportRule &&
rule.styleSheet !== null) {
n += countRules(rule.styleSheet);
}
}
return n;
}
Not run yet.
reading the result
Count the rows the auditors report: the fixture sheet has 3 of its own rules, audit-fixture.css has 3 (one of them another @import), and applied.css has 3. A phantom empty sheet adds 0 to the total — so on pre-158 Chromium the legacy auditor returns the same number as the safe one and nobody notices the landmine. (Measured bonus divergence: Chromium 141 even fetches the supports((display: pancake)) import whose condition is false and lets the auditor count its rules — watch the states line report three live sheets where a conforming engine reports two and a null.) On a nullable build the legacy auditor stops with TypeError: Cannot read properties of null. The page prints the genuine return value or the genuine exception text, nothing else.