-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[anchor-position] Properly implement CSSOM API classes
This patch adds proper implementation of the CSSPositionFallbackRule and CSSTryRule API as specified [1]: 1. It reimplements `CSSPositionFallbackRule` as a subclass of `CSSGroupingRule`, and `StyleRulePositionFallback` as a subclass of `StyleRuleGroup`. 2. It adds some code to `CSSGroupingRule.insertRule()` to make sure the function only adds `@try` rules into `CSSPositionFallbackRule`. 3. Since `CSSStyleRule.style.setProperty()` can add disallowed properties into a `@try` block [2], this patch also adds filtering into the style cascade to make sure when applying the style from a `@try` rule, only allowed properties' values are applied. This patch also manually adds the IDL of the APIs into wpt so that we can add idlharness test without waiting for the IDL auto roller. [1] https://drafts.csswg.org/css-anchor-position-1/#interfaces [2] w3c/csswg-drafts#9042 Bug: 1309178 Change-Id: Ib7700605a9968a3547fbe99197c882e8aa6caaea Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4668131 Reviewed-by: Daniil Sakhapov <sakhapov@chromium.org> Commit-Queue: Xiaocheng Hu <xiaochengh@chromium.org> Cr-Commit-Position: refs/heads/main@{#1168271}
- Loading branch information
1 parent
b9f2c32
commit 1379ecf
Showing
3 changed files
with
129 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,81 @@ | ||
<!DOCTYPE html> | ||
<title>Tests the CSSOM interfaces of @position-fallback and @try rules</title> | ||
<link rel="help" href="https://drafts.csswg.org/css-anchor-position-1/#interfaces"> | ||
<link rel="author" href="mailto:xiaochengh@chromium.org"> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
|
||
<div id="anchor"></div> | ||
<div id="not-anchor"></div> | ||
<div id="target"></div> | ||
|
||
<script> | ||
function createStyle(t, text) { | ||
const style = document.createElement('style'); | ||
style.textContent = text; | ||
t.add_cleanup(() => style.remove()); | ||
document.head.appendChild(style); | ||
return style; | ||
} | ||
|
||
test(t => { | ||
const style = createStyle( | ||
t, '@position-fallback --pf { @try { left: anchor(right); } }'); | ||
const positionFallbackRule = style.sheet.cssRules[0]; | ||
assert_true(positionFallbackRule instanceof CSSPositionFallbackRule); | ||
assert_equals(positionFallbackRule.name, '--pf'); | ||
assert_equals(positionFallbackRule.cssRules.length, 1); | ||
|
||
const tryRule = positionFallbackRule.cssRules[0]; | ||
assert_true(tryRule instanceof CSSTryRule); | ||
assert_true(tryRule.style instanceof CSSStyleDeclaration); | ||
assert_equals(tryRule.style.length, 1); | ||
assert_equals(tryRule.style.left, 'anchor(right)'); | ||
}, 'CSSPositionFallbackRule and CSSTryRule attribute values'); | ||
|
||
test(t => { | ||
const style = createStyle(t, '@position-fallback --pf {}'); | ||
const positionFallbackRule = style.sheet.cssRules[0]; | ||
|
||
assert_equals(positionFallbackRule.insertRule('@try {}', 0), 0, | ||
'@try rules can be inserted'); | ||
assert_throws_dom('HierarchyRequestError', | ||
() => positionFallbackRule.insertRule('#target { color: red; }', 1), | ||
'style rules cannot be inserted'); | ||
assert_throws_dom('HierarchyRequestError', | ||
() => positionFallbackRule.insertRule('@keyframes foo {}', 1), | ||
'other at-rules cannot be inserted'); | ||
}, 'CSSPositionFallbackRule.insertRule can insert @try rules only'); | ||
|
||
|
||
test(t => { | ||
const style = createStyle(t, ` | ||
@position-fallback --pf { @try { top: anchor(top); } } | ||
#anchor, #not-anchor, #target { | ||
position: absolute; width: 100px; height: 100px; left: 0; | ||
} | ||
#anchor { top: 100px; anchor-name: --a; } | ||
#not-anchor { top: 200px; anchor-name: --b; } | ||
#target { position-fallback: --pf; anchor-default: --a; } | ||
`); | ||
const positionFallbackRule = style.sheet.cssRules[0]; | ||
const tryRule = positionFallbackRule.cssRules[0]; | ||
|
||
// Check the initial position fallback result | ||
assert_equals(target.getBoundingClientRect().left, 0); | ||
assert_equals(target.getBoundingClientRect().top, 100); | ||
|
||
// `left` is an allowed property in `@try` and should affect position fallback. | ||
tryRule.style.setProperty('left', 'anchor(right)'); | ||
assert_equals(target.getBoundingClientRect().left, 100); | ||
assert_equals(target.getBoundingClientRect().top, 100); | ||
|
||
// These properties are disallowed in `@try` rule, and hence should not affect | ||
// position fallback. | ||
tryRule.style.setProperty('anchor-default', '--b'); | ||
tryRule.style.setProperty('position', 'static'); | ||
assert_equals(target.getBoundingClientRect().left, 100); | ||
assert_equals(target.getBoundingClientRect().top, 100); | ||
}, 'CSSTryRule.style.setProperty setting allowed and disallowed properties'); | ||
|
||
</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,37 @@ | ||
<!doctype html> | ||
<title>CSS Anchor Positioning IDL tests</title> | ||
<link rel="help" href="https://drafts.csswg.org/css-anchor-position-1/#interfaces"> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<script src="/resources/WebIDLParser.js"></script> | ||
<script src="/resources/idlharness.js"></script> | ||
|
||
<style> | ||
@position-fallback --fallback { | ||
@try {} | ||
@try {} | ||
} | ||
</style> | ||
|
||
<script> | ||
'use strict'; | ||
idl_test( | ||
['css-anchor-position'], | ||
['cssom'], | ||
idl_array => { | ||
try { | ||
self.positionFallback = document.styleSheets[0].cssRules.item(0); | ||
self.try1 = self.positionFallback.cssRules.item(0); | ||
self.try2 = self.positionFallback.cssRules.item(1); | ||
} catch (e) { | ||
// Will be surfaced when any rule is undefined below. | ||
} | ||
|
||
idl_array.add_objects({ | ||
CSSPositionFallbackRule: ['positionFallback'], | ||
CSSTryRule: ['try1', 'try2'], | ||
CSSStyleDeclaration: ['try1.style', 'try2.style'], | ||
}); | ||
} | ||
); | ||
</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,11 @@ | ||
// Source: CSS Anchor Positioning (https://drafts.csswg.org/css-anchor-position-1/) | ||
|
||
[Exposed=Window] | ||
interface CSSPositionFallbackRule : CSSGroupingRule { | ||
readonly attribute CSSOMString name; | ||
}; | ||
|
||
[Exposed=Window] | ||
interface CSSTryRule : CSSRule { | ||
[SameObject, PutForwards=cssText] readonly attribute CSSStyleDeclaration style; | ||
}; |