forked from mirrors/gecko-dev
Currently Firefox properly performs validation of an @property rule, as defined in [1]. However when such a rule is invalid, it only does not register the custom property instead of dropping the whole rule. Other implementations also follow that aproach and existing web platform tests disagree with the specification [2]. This patch aligns Firefox's behavior with the specification, by moving @property validation during parsing and dropping invalid rules. Tests are updated as follows: 1. /css/css-properties-values-api/at-property-cssom.html Existing tests that don't have the three descriptors (syntax, inherit, initial-value) are invalid and now the test verifies no corresponding rules are exposed via CSSOM. `--no-initial-value` is renamed `--no-initial-color-value` and its legacy tests are kept for a new @property `--no-initial-universal-value` which uses the universal syntax (so initial value is optional). Some dummy descriptors are added for --tab\ttab so that it remains valid. Similarly, we ensure --valid-whitespace's syntax (space-separated) and initial-value (comma-separated) agree. 2. /css/css-properties-values-api/at-property.html Existing `test_descriptor()` tests are trying an @property with a single specified descriptor and so are always invalid. To work around that, we tweak `test_descriptor()` so that it can build a valid descriptor instead. The `syntax` and `inherits` fallback to universal and true respectively while the `initial-value` descriptor is built from the `syntax`. An extra parameters is introduced in case the caller wants to provide these values directly. Finally, when the expected value is null the function instead verifies that the rule is really dropped. 2.1. Some existing syntax tests are registering rules with unquoted syntax value 'red', 'rgb(255, 0, 0)', 'color', 'foo | bar' and expect to obtain a rule with an empty syntax string, suggesting some kind of invalidity handling (cf similar tests). We interpret the first two as "specifying a color value", quotes are added and the first one actually becomes a valid custom-ident. The last two already have a similar quoted version, so we just interpret them as "missing quotes". 2.2. Given the previous 'red' custom-ident, we add tests for invalid custom-ident as defined in [3]. 2.3. Some existing `syntax` tests are checking that we must have "pipe between components" and no "leading bar" and are again expecting a rule with an empty syntax string. We fix the apparent mistake of missing quotes and provide initial values that could potentially be interpreted as correct by implementations accepting these invalid syntaxes. 2.4. One `initial-value` test is checking "var(--x)" but that is not computationally independent so tweak the test to check that makes the @property rule invalid. Also add a similar '3em' test mentioned in the spec. 2.5. Some `inherits` tests verify that invalid rules are interpreted as false. It seems they should instead be treated as if it does not exist and so should make the @property rule invalid. [1] https://drafts.css-houdini.org/css-properties-values-api-1/#at-property-rule [2] https://github.com/w3c/css-houdini-drafts/issues/1098 [3] https://drafts.csswg.org/css-values-4/#custom-idents Differential Revision: https://phabricator.services.mozilla.com/D190444
191 lines
5.4 KiB
HTML
191 lines
5.4 KiB
HTML
<!DOCTYPE html>
|
|
<link rel="help" href="https://drafts.css-houdini.org/css-properties-values-api-1/#cssom">
|
|
<script src="/resources/testharness.js"></script>
|
|
<script src="/resources/testharnessreport.js"></script>
|
|
<style>
|
|
@property --valid {
|
|
syntax: "<color> | none";
|
|
inherits: false;
|
|
initial-value: red;
|
|
}
|
|
@property --valid-reverse {
|
|
initial-value: 0px;
|
|
inherits: true;
|
|
syntax: "<length>";
|
|
}
|
|
@property --valid-universal {
|
|
syntax: "*";
|
|
inherits: false;
|
|
}
|
|
@property --valid-whitespace {
|
|
syntax: " <color># ";
|
|
inherits: false;
|
|
initial-value: red, blue;
|
|
}
|
|
@property --vALId {
|
|
syntax: "<color> | none";
|
|
inherits: false;
|
|
initial-value: red;
|
|
}
|
|
@property --no-descriptors {
|
|
|
|
}
|
|
@property --no-syntax {
|
|
inherits: false;
|
|
initial-value: red;
|
|
}
|
|
@property --no-inherits {
|
|
syntax: "<color> | none";
|
|
initial-value: red;
|
|
}
|
|
@property --no-initial-color-value {
|
|
syntax: "<color> | none";
|
|
inherits: false;
|
|
}
|
|
@property --no-initial-universal-value {
|
|
syntax: "*";
|
|
inherits: false;
|
|
}
|
|
@property --syntax-only {
|
|
syntax: "<color> | none";
|
|
}
|
|
@property --inherits-only {
|
|
inherits: true;
|
|
}
|
|
@property --initial-value-only {
|
|
initial-value: red;
|
|
}
|
|
/* U+0009 CHARACTER TABULATION */
|
|
@property --tab\9 tab {
|
|
syntax: "*";
|
|
inherits: true;
|
|
}
|
|
</style>
|
|
<script>
|
|
|
|
function find_at_property_rule(name) {
|
|
for (let rule of document.styleSheets[0].cssRules) {
|
|
if (rule.constructor.name != "CSSPropertyRule")
|
|
continue;
|
|
if (rule.name == name)
|
|
return rule;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function test_invalid(name) {
|
|
test(() => {
|
|
let rule = find_at_property_rule(name);
|
|
assert_true(!rule);
|
|
}, `Rule for ${name} is invalid`);
|
|
}
|
|
|
|
function test_css_text(name, expected) {
|
|
test(() => {
|
|
let rule = find_at_property_rule(name);
|
|
assert_true(!!rule);
|
|
assert_equals(rule.cssText, expected);
|
|
}, `Rule for ${name} has expected cssText`);
|
|
}
|
|
|
|
function test_name(name) {
|
|
test(() => {
|
|
let rule = find_at_property_rule(name);
|
|
assert_true(!!rule);
|
|
assert_equals(rule.name, name);
|
|
}, `Rule for ${name} returns expected value for CSSPropertyRule.name`);
|
|
}
|
|
|
|
function test_syntax(name, expected) {
|
|
test(() => {
|
|
let rule = find_at_property_rule(name);
|
|
assert_true(!!rule);
|
|
assert_equals(rule.syntax, expected);
|
|
}, `Rule for ${name} returns expected value for CSSPropertyRule.syntax`);
|
|
}
|
|
|
|
function test_inherits(name, expected) {
|
|
test(() => {
|
|
let rule = find_at_property_rule(name);
|
|
assert_true(!!rule);
|
|
assert_equals(rule.inherits, expected);
|
|
}, `Rule for ${name} returns expected value for CSSPropertyRule.inherits`);
|
|
}
|
|
|
|
function test_initial_value(name, expected) {
|
|
test(() => {
|
|
let rule = find_at_property_rule(name);
|
|
assert_true(!!rule);
|
|
assert_equals(rule.initialValue, expected);
|
|
}, `Rule for ${name} returns expected value for CSSPropertyRule.initialValue`);
|
|
}
|
|
|
|
// Invalid @property rules.
|
|
test_invalid('--no-descriptors');
|
|
test_invalid('--no-syntax');
|
|
test_invalid('--no-inherits');
|
|
test_invalid('--no-initial-color-value');
|
|
test_invalid('--syntax-only', '@property --syntax-only { syntax: "<color> | none"; }');
|
|
test_invalid('--inherits-only', '@property --inherits-only { inherits: true; }');
|
|
test_invalid('--initial-value-only', '@property --initial-value-only { initial-value: red; }');
|
|
|
|
// CSSPropertyRule.cssText
|
|
|
|
test_css_text('--valid', '@property --valid { syntax: "<color> | none"; inherits: false; initial-value: red; }');
|
|
test_css_text('--valid-reverse', '@property --valid-reverse { syntax: "<length>"; inherits: true; initial-value: 0px; }');
|
|
test_css_text('--valid-universal', '@property --valid-universal { syntax: "*"; inherits: false; }');
|
|
test_css_text('--valid-whitespace', '@property --valid-whitespace { syntax: " <color># "; inherits: false; initial-value: red, blue; }');
|
|
test_css_text('--vALId', '@property --vALId { syntax: "<color> | none"; inherits: false; initial-value: red; }');
|
|
|
|
test_css_text('--no-initial-universal-value', '@property --no-initial-universal-value { syntax: "*"; inherits: false; }');
|
|
|
|
test_css_text('--tab\ttab', '@property --tab\\9 tab { syntax: "*"; inherits: true; }');
|
|
|
|
// CSSRule.type
|
|
|
|
test(() => {
|
|
let rule = find_at_property_rule('--valid');
|
|
assert_equals(rule.type, 0);
|
|
}, 'CSSRule.type returns 0');
|
|
|
|
// CSSPropertyRule.name
|
|
|
|
test_name('--valid');
|
|
test_name('--valid-reverse');
|
|
test_name('--valid-universal');
|
|
test_name('--valid-whitespace');
|
|
test_name('--vALId');
|
|
|
|
test_name('--no-initial-universal-value');
|
|
|
|
// CSSPropertyRule.syntax
|
|
|
|
test_syntax('--valid', '<color> | none');
|
|
test_syntax('--valid-reverse', '<length>');
|
|
test_syntax('--valid-universal', '*');
|
|
test_syntax('--valid-whitespace', ' <color># ');
|
|
test_syntax('--vALId', '<color> | none');
|
|
|
|
test_syntax('--no-initial-universal-value', '*');
|
|
|
|
// CSSPropertyRule.inherits
|
|
|
|
test_inherits('--valid', false);
|
|
test_inherits('--valid-reverse', true);
|
|
test_inherits('--valid-universal', false);
|
|
test_inherits('--valid-whitespace', false);
|
|
test_inherits('--vALId', false);
|
|
|
|
test_inherits('--no-initial-universal-value', false);
|
|
|
|
// CSSPropertyRule.initialValue
|
|
|
|
test_initial_value('--valid', 'red');
|
|
test_initial_value('--valid-reverse', '0px');
|
|
test_initial_value('--valid-universal', null);
|
|
test_initial_value('--valid-whitespace', 'red, blue');
|
|
test_initial_value('--vALId', 'red');
|
|
|
|
test_initial_value('--no-initial-universal-value', null);
|
|
|
|
</script>
|