Skip to content

Commit

Permalink
[anchor] Implement CSSPositionTryDescriptors
Browse files Browse the repository at this point in the history
CSSPositionTryDescriptors is a CSSStyleDeclaration which restricts
which properties are valid, which is a new concept in Blink.
This CL implements this by:

 - Adding a new parsing mode which is stored on the CSSPropertyValueSet
   within the rule. This ensures that we can't smuggle in invalid
   properties using cssText.
 - Filtering properties during setProperty. This ensures that e.g.
   setProperty('color', ...) doesn't work.

Somehow, CSSPositionTryDescriptor is not inheriting the anonymous
named getter/setter from the parent, which is actually what we want
here. (If this is a bug or something and is changed later, the WPT will
fail).

The indexed property getter also doesn't seem to work. This is not
covered by the tests currently. The problem is tracked by
Issue 333965945.

Change-Id: I5fa1b600ed50633a9eb9aa8cfeb43726d64ecf90
Bug: 333967631, 333965945
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5447110
Reviewed-by: Rune Lillesveen <[email protected]>
Reviewed-by: Philip Jägenstedt <[email protected]>
Commit-Queue: Anders Hartvoll Ruud <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1287213}
  • Loading branch information
andruud authored and chromium-wpt-export-bot committed Apr 15, 2024
1 parent 6eb4b61 commit 9fcc5e1
Showing 1 changed file with 137 additions and 1 deletion.
138 changes: 137 additions & 1 deletion css/css-anchor-position/at-position-try-cssom.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
const positionTryRule = style.sheet.cssRules[0];
assert_true(positionTryRule instanceof CSSPositionTryRule);
assert_equals(positionTryRule.name, '--pf');
assert_true(positionTryRule.style instanceof CSSStyleDeclaration);
assert_true(positionTryRule.style instanceof CSSPositionTryDescriptors);
assert_equals(positionTryRule.style.length, 1);
assert_equals(positionTryRule.style.left, 'anchor(right)');
}, 'CSSPositionTryRule attribute values');
Expand Down Expand Up @@ -63,4 +63,140 @@

}, 'CSSPositionTryRule.style.setProperty setting allowed and disallowed properties');

test(t => {
const style = createStyle(t, `
@position-try --pf {
top: 10px;
left: 20px;
--x: 200px;
color: red;
}
`);
let declarations = style.sheet.cssRules[0].style;
assert_equals(declarations.length, 2);
assert_equals(declarations.item(0), 'top');
assert_equals(declarations.item(1), 'left');
}, 'CSSPositionTryDescriptors.item');

test(t => {
const style = createStyle(t, '@position-try --pf {}');
let declarations = style.sheet.cssRules[0].style;
assert_equals(declarations.length, 0);
declarations.cssText = `color:red;top:10px;`;
assert_equals(declarations.length, 1);
}, 'CSSPositionTryDescriptors.cssText');

let supported_properties = [
'margin',
'margin-top',
'margin-right',
'margin-bottom',
'margin-left',
'margin-block',
'margin-block-start',
'margin-block-end',
'margin-inline',
'margin-inline-start',
'margin-inline-end',
'inset',
'top',
'left',
'right',
'bottom',
'inset-block',
'inset-block-start',
'inset-block-end',
'inset-inline',
'inset-inline-start',
'inset-inline-end',
'width',
'height',
'min-width',
'max-width',
'min-height',
'max-height',
'block-size',
'min-block-size',
'max-block-size',
'inline-size',
'min-inline-size',
'max-inline-size',
'place-self',
'align-self',
'justify-self',
'position-anchor',
'inset-area',
];

// A selection of unsupported properties.
let unsupported_properties = [
'color',
'align-items',
'align-content',
'background',
'display',
'position',
'writing-mode',
'direction',
'syntax', // @property
];

let upperFirst = (x) => x[0].toUpperCase() + x.slice(1);
let lowerFirst = (x) => x[0].toLowerCase() + x.slice(1);
let toLowerCamelCase = (x) => lowerFirst(x.split('-').map(upperFirst).join(''));

// Test getting/setting the specified property on a CSSPositionTryDescriptors
// object. The property can either be supported or not supported,
// which determines the expected results.
function test_property(prop, supported) {
test(t => {
let decls = supported_properties.map(x => `${x}:unset;`).join('');
let style = createStyle(t, `@position-try --pf { ${decls} }`);
let declarations = style.sheet.cssRules[0].style;
assert_equals(declarations.getPropertyValue(prop), supported ? 'unset' : '');
}, `CSSPositionTryDescriptors.getPropertyValue(${prop})`);

test(t => {
let style = createStyle(t, '@position-try --pf {}');
let declarations = style.sheet.cssRules[0].style;
declarations.setProperty(prop, 'unset');
assert_equals(declarations.getPropertyValue(prop), supported ? 'unset' : '');
}, `CSSPositionTryDescriptors.setProperty(${prop})`);

test(t => {
let decls = supported_properties.map(x => `${x}:unset;`).join('');
let style = createStyle(t, `@position-try --pf { ${decls} }`);
let declarations = style.sheet.cssRules[0].style;
assert_equals(declarations[prop], supported ? 'unset' : undefined);
}, `CSSPositionTryDescriptors[${prop}] (set)`);

test(t => {
let style = createStyle(t, '@position-try --pf {}');
let declarations = style.sheet.cssRules[0].style;
declarations[prop] = 'unset';
assert_equals(declarations.getPropertyValue(prop), supported ? 'unset' : '');
}, `CSSPositionTryDescriptors[${prop}] (get)`);

let camelCaseAttr = toLowerCamelCase(prop);
if (camelCaseAttr != prop) {
// Also test the camelCase version of the attribute.
test(t => {
let decls = supported_properties.map(x => `${x}:unset;`).join('');
let style = createStyle(t, `@position-try --pf { ${decls} }`);
let declarations = style.sheet.cssRules[0].style;
assert_equals(declarations[camelCaseAttr], supported ? 'unset' : undefined);
}, `CSSPositionTryDescriptors[${camelCaseAttr}] (get)`);

test(t => {
let style = createStyle(t, '@position-try --pf {}');
let declarations = style.sheet.cssRules[0].style;
declarations[camelCaseAttr] = 'unset';
assert_equals(declarations.getPropertyValue(prop), supported ? 'unset' : '');
}, `CSSPositionTryDescriptors[${camelCaseAttr}] (set)`);
}
}

supported_properties.forEach(x => { test_property(x, /* supported */ true); });
unsupported_properties.forEach(x => { test_property(x, /* supported */ false); });

</script>

0 comments on commit 9fcc5e1

Please sign in to comment.