Files
sousa-gecko/testing/web-platform/tests/css/css-cascade/revert-rule-important.html
T
Anders Hartvoll Ruud e9e25e7e8e Bug 2015085 [wpt PR 57615] - [revert-rule] Insert weak CascadePriority objects into CascadeMap, a=testonly
Automatic update from web-platform-tests
[revert-rule] Insert weak CascadePriority objects into CascadeMap

Every time a CascadePriority is added to the CascadeMap,
we check if it's stronger than the current winner of the same
property. If it is, we insert that CascadePriority to the front
of a list, with the rest of the list containing all previously
seen winners.

In a world without !important, this would be enough to implement
'revert-rule', since rules are sorted based on position/layer (etc)
before they are added to the CascadeMap. This is not possible
for !important, since that is a declaration-level modifier.

For example, the following should be 'green':

  div {
    color: red;
  }
  div {
    color: revert-rule !important;
  }
  div {
    color: green;
  }

These rules are added to the cascade map in the specified order
(which happens to match the rule-sorted order), which means that:

  1. We see "color:red", and add it to the map.
  2. We see "color:revert-rule !important", and being stronger that
     the declaration from (1), we add that the the front of the list.
  3. We see "color:green", which is *weaker* that the declaration from
     (2), so we just discard it.

To implement 'revert-rule' correctly, we can no longer just discard
weak declarations; we must sort them into the list, which is what
this CL does.

Speedometer3 shows no significant change, nor does StyleCalcPerfTest.

Note that in this specific example, we don't *really* need to
keep "red" around in the list ("green" could overwrite "red"
in-place). However, we cannot *always* do this, because
'revert-rule' can appear dynamically through 'if()' (etc).
For example, if we instead of color:green had the following:

  color: if(style(--x:on):green;else:revert-rule);

Then in the 'on' case, it's safe to overwrite "red", but in
other cases it ("red") needs to be there so we can revert to it.
Reverts can also appear from values that don't contain "revert"
literally, e.g. a custom function call, or the ident() function.
We *could* add a fast path for any non-unparsed declaration,
but, since its effects wouldn't be measurable under the benchmarks
we currently care about, it doesn't seem worth it.

Fixed: 478178033
Change-Id: I9ef618c0eed2f78ec9698840d2114dba8823f55b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7535261
Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org>
Reviewed-by: Steinar H Gunderson <sesse@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1580858}

--

wpt-commits: 0cc02b8a0bb09aa5599986dae0196d95c679e62b
wpt-pr: 57615
2026-02-12 13:03:13 +00:00

52 lines
1.3 KiB
HTML

<!DOCTYPE html>
<title>The revert-rule keyword: interaction with !important</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#revert-rule-keyword">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
#test1 {
color: revert-rule !important;
}
#test1 {
color: green;
}
</style>
<div id="test1"></div>
<script>
test(() => {
assert_true(CSS.supports('color:revert-rule'));
assert_equals(getComputedStyle(test1).color, 'rgb(0, 128, 0)');
}, 'revert-rule in !important declaration reverts to later normal rule if the !important rule comes first');
</script>
<style>
@layer {
#test2 {
color: revert-rule !important;
}
}
#test2 {
color: green;
}
</style>
<div id='test2'></div>
<script>
test(() => {
assert_equals(getComputedStyle(test2).color, 'rgb(0, 128, 0)');
}, 'revert-rule in !important declaration reverts across layers');
</script>
<style>
#test3 {
color: green;
}
#test3 {
color: revert-rule !important;
}
</style>
<div id='test3'></div>
<script>
test(() => {
assert_equals(getComputedStyle(test3).color, 'rgb(0, 128, 0)');
}, 'revert-rule in !important declaration reverts to earlier normal rule if the !important rule comes later');
</script>