-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
This CL implements the ability to scope an entire stylesheet on import, via the new scope() function. The CSSWG has resolved to add the scope() function, but there is no spec yet. The WPTs are therefore marked as tentative for now. Note that this CL intentionally does not have parse-validity tests, such as scope() combined with other features of the @import prelude (e.g. layer(), media queries). This is because scope()'s "position" in the prelude grammar has not been defined, and the WG instead resolved allow full reordering of the conditions. This opens a new problem, tracked by Issue 10972 [1]. In other words, parsing tests are deferred until that issue is resolved. The WPTs in this only use @import scope(...)", which is assumed to be valid regardless of the outcome. Since regular top-level selectors are not relative selectors, they are not guaranteed to contain either '&' or ':scope' like selector parsing nested under CSSNestingType::kNesting or CSSNestingType::kScope (respectively). This means that selectors at the top-level of an imported stylesheet are not guaranteed to be scope-containing, so we need another way of enforcing the in-scope [2] requirement of scoped selectors. This is effectively done by always treating the last selector in a complex selector as scope-containing. Due to the same absence of '&' and ':scope' in the imported stylesheet, rules can also be incorrectly handled as "easy" or "covered by bucketing" even though they match in the context of a scope. Addressed this by disabling the optimization when context.style_scope is set. [1] w3c/csswg-drafts#10972 [2] https://drafts.csswg.org/css-cascade-6/#in-scope Bug: 369876911 Change-Id: I75bc3514d959c6762232bc769f844682ed4a50fd Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6012179 Commit-Queue: Anders Hartvoll Ruud <[email protected]> Reviewed-by: Rune Lillesveen <[email protected]> Cr-Commit-Position: refs/heads/main@{#1383152}
- Loading branch information
1 parent
c6cbeb6
commit 8c083dd
Showing
8 changed files
with
219 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
.x { | ||
--x: 1; | ||
} | ||
|
||
:scope > .y { | ||
--y: 1; | ||
} | ||
|
||
@scope (.inner-scope) { | ||
.z { | ||
--z: 1; | ||
} | ||
} | ||
|
||
& > .w { | ||
--w: 1; | ||
} | ||
|
||
& > & > .u { | ||
--u: 1; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<!DOCTYPE html> | ||
<title>@import scope(), implicit scope</title> | ||
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/7348"> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<main id=main> | ||
<div class=scope> | ||
<style> | ||
@import url("resources/scope-imported.css") scope(); | ||
</style> | ||
<div class=x>Inside</div> | ||
</div> | ||
<div class=x>Outside</div> | ||
</main> | ||
<script> | ||
test(() => { | ||
let e = main.querySelector('.scope > .x'); | ||
assert_equals(getComputedStyle(e).getPropertyValue('--x'), '1'); | ||
}, 'Scope-imported rule applies within implicit scope'); | ||
|
||
test(() => { | ||
let e = main.querySelector('main > .x'); | ||
assert_equals(getComputedStyle(e).getPropertyValue('--x'), ''); | ||
}, 'Scope-imported rule does not apply outside of implicit scope'); | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
<!DOCTYPE html> | ||
<title>@import scope(), :scope rules in imported stylesheet</title> | ||
<link rel="help" href="https://drafts.csswg.org/css-cascade-6/#scope-atrule"> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<style> | ||
@import url("resources/scope-imported.css") scope((.scope)); | ||
</style> | ||
<main id=main> | ||
<div class=scope> | ||
<div class=inner-scope> | ||
<div class=z>Inside</div> | ||
</div> | ||
</div> | ||
<div class=inner-scope> | ||
<div class=z>Outside</div> | ||
</div> | ||
</main> | ||
<script> | ||
test(() => { | ||
let e = main.querySelector('.scope > .inner-scope > .z'); | ||
assert_equals(getComputedStyle(e).getPropertyValue('--z'), '1'); | ||
}, '@scope within scope-imported stylesheet matches'); | ||
|
||
test(() => { | ||
let e = main.querySelector('#main > .inner-scope > .z'); | ||
assert_equals(getComputedStyle(e).getPropertyValue('--z'), ''); | ||
}, '@scope within scope-imported does not ignore import scope'); | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<!DOCTYPE html> | ||
<title>@import scope(), same stylesheet imported multiple times</title> | ||
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/7348"> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<style> | ||
@import url("resources/scope-imported.css") scope((.scope1)); | ||
@import url("resources/scope-imported.css") scope((.scope2)); | ||
</style> | ||
<main id=main> | ||
<div class=scope1> | ||
<div class=x>Inside</div> | ||
</div> | ||
<div class=scope2> | ||
<div class=x>Inside</div> | ||
</div> | ||
<div class=x>Outside</div> | ||
</main> | ||
<script> | ||
test(() => { | ||
let e1 = main.querySelector('.scope1 > .x'); | ||
let e2 = main.querySelector('.scope2 > .x'); | ||
assert_equals(getComputedStyle(e1).getPropertyValue('--x'), '1'); | ||
assert_equals(getComputedStyle(e2).getPropertyValue('--x'), '1'); | ||
}, 'A stylesheet may be imported multiple times, and scoped differently'); | ||
|
||
test(() => { | ||
let e = main.querySelector('main > .x'); | ||
assert_equals(getComputedStyle(e).getPropertyValue('--x'), ''); | ||
}, 'Scope-imported rule does not apply outside of scope'); | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<!DOCTYPE html> | ||
<title>@import scope(), '&' selectors</title> | ||
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/7348"> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<style> | ||
@import url("resources/scope-imported.css") scope((.scope)); | ||
</style> | ||
<main id=main> | ||
<div class=scope> | ||
<div class=w>Inside</div> | ||
<div class=scope> | ||
<div class=w>Inner (W)</div> | ||
<div class=u>Inner (U)</div> | ||
</div> | ||
</div> | ||
</main> | ||
<script> | ||
test(() => { | ||
let e = main.querySelector('#main > .scope > .w'); | ||
assert_equals(getComputedStyle(e).getPropertyValue('--w'), '1'); | ||
}, 'The & selector matches the scoping root'); | ||
|
||
test(() => { | ||
let w = main.querySelector('#main > .scope > .scope > .w'); | ||
assert_equals(getComputedStyle(w).getPropertyValue('--w'), '1'); | ||
// The '& > & > .u' selector should behave like ':scope > :scope > .u' | ||
// and therefore never match. | ||
let u = main.querySelector('#main > .scope > .scope > .u'); | ||
assert_equals(getComputedStyle(u).getPropertyValue('--u'), ''); | ||
}, 'The & selector behaves like :scope'); | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<!DOCTYPE html> | ||
<title>@import scope() with <scope-end></title> | ||
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/7348"> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<style> | ||
@import url("resources/scope-imported.css") scope((.scope) to (.limit)); | ||
</style> | ||
<main id=main> | ||
<div class=scope> | ||
<div class=x>Inside</div> | ||
<div class=limit> | ||
<div class=x>Below limit</div> | ||
</div> | ||
</div> | ||
</main> | ||
<script> | ||
test(() => { | ||
let e = main.querySelector('.scope > .x'); | ||
assert_equals(getComputedStyle(e).getPropertyValue('--x'), '1'); | ||
}, 'Scope-imported rule applies within scope, above limit'); | ||
|
||
test(() => { | ||
let e = main.querySelector('.limit > .x'); | ||
assert_equals(getComputedStyle(e).getPropertyValue('--x'), ''); | ||
}, 'Scope-imported rule does not apply below limit'); | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
<!DOCTYPE html> | ||
<title>@import scope(), :scope rules in imported stylesheet</title> | ||
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/7348"> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<style> | ||
@import url("resources/scope-imported.css") scope((.scope)); | ||
</style> | ||
<main id=main> | ||
<div class=scope> | ||
<div class=y>Inside</div> | ||
<div> | ||
<div class=y>Inside, but should not match</div> | ||
</div> | ||
</div> | ||
<div class=y>Outside</div> | ||
</main> | ||
<script> | ||
test(() => { | ||
let inside = main.querySelector('.scope > .y'); | ||
assert_equals(getComputedStyle(inside).getPropertyValue('--y'), '1'); | ||
|
||
let inside_no_match = main.querySelector('.scope > div > .y'); | ||
assert_equals(getComputedStyle(inside_no_match).getPropertyValue('--y'), ''); | ||
|
||
let outside = main.querySelector('#main > .y'); | ||
assert_equals(getComputedStyle(outside).getPropertyValue('--y'), ''); | ||
}, 'The :scope pseudo-class works in imported stylesheets'); | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<!DOCTYPE html> | ||
<title>@import scope(), <scope-start></title> | ||
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/7348"> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<style> | ||
@import url("resources/scope-imported.css") scope((.scope)); | ||
</style> | ||
<main id=main> | ||
<div class=scope> | ||
<div class=x>Inside</div> | ||
</div> | ||
<div class=x>Outside</div> | ||
</main> | ||
<script> | ||
test(() => { | ||
let e = main.querySelector('.scope > .x'); | ||
assert_equals(getComputedStyle(e).getPropertyValue('--x'), '1'); | ||
}, 'Scope-imported rule applies within scope'); | ||
|
||
test(() => { | ||
let e = main.querySelector('main > .x'); | ||
assert_equals(getComputedStyle(e).getPropertyValue('--x'), ''); | ||
}, 'Scope-imported rule does not apply outside of scope'); | ||
</script> |