Commit 47b0b6ca authored by Darren Shen's avatar Darren Shen Committed by Commit Bot

[css-typed-om] Normalize custom property declarations.

When parsing custom properties or retrieving them from CSSOM, we need
to return a CSSUnparsedValue.

Spec: https://drafts.css-houdini.org/css-typed-om-1/#normalize-tokens

Bug: 788570, 779477
Change-Id: Ia2fa289dc076ffd6dbacf03822907663209c6284
Reviewed-on: https://chromium-review.googlesource.com/804920Reviewed-by: default avatarnainar <nainar@chromium.org>
Commit-Queue: Darren Shen <shend@chromium.org>
Cr-Commit-Position: refs/heads/master@{#521969}
parent fe2b322b
...@@ -43,7 +43,7 @@ registerPaint('geometry', class { ...@@ -43,7 +43,7 @@ registerPaint('geometry', class {
ctx.strokeStyle = 'green'; ctx.strokeStyle = 'green';
if (serializedStrings[0] != "--bar: [null]") if (serializedStrings[0] != "--bar: [null]")
ctx.strokeStyle = 'red'; ctx.strokeStyle = 'red';
if (serializedStrings[1] != "--foo: [CSSStyleValue= bar]") if (serializedStrings[1] != "--foo: [CSSUnparsedValue= bar]")
ctx.strokeStyle = 'blue'; ctx.strokeStyle = 'blue';
if (serializedStrings[2] != "align-items: [CSSKeywordValue=normal]") if (serializedStrings[2] != "align-items: [CSSKeywordValue=normal]")
ctx.strokeStyle = 'yellow'; ctx.strokeStyle = 'yellow';
......
...@@ -46,7 +46,7 @@ registerPaint('geometry', class { ...@@ -46,7 +46,7 @@ registerPaint('geometry', class {
ctx.strokeStyle = 'green'; ctx.strokeStyle = 'green';
if (serializedStrings[0] != "--bar: [null]") if (serializedStrings[0] != "--bar: [null]")
ctx.strokeStyle = 'red'; ctx.strokeStyle = 'red';
if (serializedStrings[1] != "--foo: [CSSStyleValue= bar]") if (serializedStrings[1] != "--foo: [CSSUnparsedValue= bar]")
ctx.strokeStyle = 'blue'; ctx.strokeStyle = 'blue';
if (serializedStrings[2] != "border-radius: [CSSStyleValue=2px]") if (serializedStrings[2] != "border-radius: [CSSStyleValue=2px]")
ctx.strokeStyle = 'yellow'; ctx.strokeStyle = 'yellow';
......
...@@ -8,6 +8,16 @@ ...@@ -8,6 +8,16 @@
<script> <script>
'use strict'; 'use strict';
function assert_string_normalizes_to(property, str, expected) {
// From string
assert_style_value_equals(CSSStyleValue.parse(property, str), expected);
// From CSSOM
assert_style_value_equals(
newDivWithStyle(property + ':' + str).attributeStyleMap.get(property),
expected
);
}
const gTestCases = [ const gTestCases = [
{ {
value: 'var(--A)', value: 'var(--A)',
...@@ -40,16 +50,13 @@ const gTestCases = [ ...@@ -40,16 +50,13 @@ const gTestCases = [
]; ];
for (const {value, expectedResult} of gTestCases) { for (const {value, expectedResult} of gTestCases) {
// TODO(788570): Add similar tests using a custom property instead of 'color'
test(() => { test(() => {
const result = CSSStyleValue.parse('color', value); assert_string_normalizes_to('color', value, new CSSUnparsedValue(...expectedResult));
assert_style_value_equals(result, new CSSUnparsedValue(...expectedResult)); }, 'Normalizing "' + value + '" on a CSS property returns correct CSSUnparsedValue');
}, 'Normalizing "' + value + '" from String returns correct CSSUnparsedValue');
test(() => { test(() => {
const result = newDivWithStyle('color:' + value).attributeStyleMap.get('color'); assert_string_normalizes_to('--X', value, new CSSUnparsedValue(...expectedResult));
assert_style_value_equals(result, new CSSUnparsedValue(...expectedResult)); }, 'Normalizing "' + value + '" on a custom property returns correct CSSUnparsedValue');
}, 'Normalizing "' + value + '" from CSSOM returns correct CSSUnparsedValue');
} }
</script> </script>
This is a testharness.js-based test.
PASS Calling CSSStyleValue.parse with an empty string throws a TypeError
PASS Calling CSSStyleValue.parse with an unsupported CSS property throws a TypeError
PASS Calling CSSStyleValue.parse with a CSS shorthand throws a TypeError
PASS Calling CSSStyleValue.parse with an invalid cssText for the given property throws a SyntaxError
PASS Calling CSSStyleValue.parseAll with an empty string throws a TypeError
PASS Calling CSSStyleValue.parseAll with an unsupported CSS property throws a TypeError
PASS Calling CSSStyleValue.parseAll with a CSS shorthand throws a TypeError
PASS Calling CSSStyleValue.parseAll with an invalid cssText for the given property throws a SyntaxError
PASS Calling CSSStyleValue.parse with a valid cssText for the given property returns a valid CSSStyleValue
PASS Calling CSSStyleValue.parse with a mixed case cssText returns a valid CSSStyleValue
FAIL Calling CSSStyleValue.parse with a custom property returns a valid CSSStyleValue Failed to execute 'parse' on 'CSSStyleValue': Invalid property name
PASS Calling CSSStyleValue.parseAll with a valid cssText for the given property returns a single-element list containing a valid CSSStyleValue
PASS Calling CSSStyleValue.parseAll with a mixed case cssText returns a single-element list containing a valid CSSStyleValue
FAIL Calling CSSStyleValue.parseAll with a custom property returns a single-element list containing a valid CSSStyleValue Failed to execute 'parseAll' on 'CSSStyleValue': Invalid property name
PASS Calling CSSStyleValue.parse with a list-value property returns first list value
PASS Calling CSSStyleValue.parseAll with a list-value property returns a sequence of values
Harness: the test ran to completion.
...@@ -30,7 +30,7 @@ for (const parseMethod of ['parse', 'parseAll']) { ...@@ -30,7 +30,7 @@ for (const parseMethod of ['parse', 'parseAll']) {
const gValidNonListTests = [ const gValidNonListTests = [
{ property: 'width', value: '10px', expected: CSS.px(10), desc: 'a valid cssText for the given property' }, { property: 'width', value: '10px', expected: CSS.px(10), desc: 'a valid cssText for the given property' },
{ property: 'wIdTh', value: '10px', expected: CSS.px(10), desc: 'a mixed case cssText' }, { property: 'wIdTh', value: '10px', expected: CSS.px(10), desc: 'a mixed case cssText' },
{ property: '--foo', value: '10%', expected: CSS.percent(10), desc: 'a custom property' }, { property: '--foo', value: '10%', expected: new CSSUnparsedValue('10%'), desc: 'a custom property' },
]; ];
for (const {property, value, expected, desc} of gValidNonListTests) { for (const {property, value, expected, desc} of gValidNonListTests) {
......
This is a testharness.js-based test. This is a testharness.js-based test.
FAIL Computed StylePropertyMap contains every CSS property assert_equals: expected 296 but got 294 FAIL Computed StylePropertyMap contains every CSS property assert_equals: expected 296 but got 294
PASS Computed StylePropertyMap contains CSS property declarations in style rules PASS Computed StylePropertyMap contains CSS property declarations in style rules
FAIL Computed StylePropertyMap contains custom property declarations in style rules assert_equals: expected "CSSUnparsedValue" but got "CSSStyleValue" PASS Computed StylePropertyMap contains custom property declarations in style rules
PASS Computed StylePropertyMap contains CSS property declarations in inline styles PASS Computed StylePropertyMap contains CSS property declarations in inline styles
FAIL Computed StylePropertyMap contains custom property declarations in inline rules assert_equals: expected "CSSUnparsedValue" but got "CSSStyleValue" PASS Computed StylePropertyMap contains custom property declarations in inline rules
PASS Computed StylePropertyMap contains computed values and not resolved values PASS Computed StylePropertyMap contains computed values and not resolved values
PASS Computed StylePropertyMap is live PASS Computed StylePropertyMap is live
Harness: the test ran to completion. Harness: the test ran to completion.
......
This is a testharness.js-based test.
PASS Calling StylePropertyMap.get with an unsupported property throws a TypeError
PASS Calling StylePropertyMap.get with a property not in the property model returns null
PASS Calling StylePropertyMap.get with a custom property not in the property model returns null
PASS Calling StylePropertyMap.get with a valid property returns the correct entry
PASS StylePropertyMap.get with a valid property in mixed case returns the correct entry
FAIL Calling StylePropertyMap.get with a valid custom property returns the correct entry assert_equals: expected "CSSUnparsedValue" but got "CSSStyleValue"
PASS Calling StylePropertyMap.get with a list-valued property returns only the first value
Harness: the test ran to completion.
This is a testharness.js-based test.
PASS Calling StylePropertyMap.getAll with an unsupported property throws a TypeError
PASS Calling StylePropertyMap.getAll with a property not in the property model returns an empty list
PASS Calling StylePropertyMap.getAll with a custom property not in the property model returns an empty list
PASS Calling StylePropertyMap.getAll with a valid property returns a single element list with the correct entry
PASS StylePropertyMap.getAll is case-insensitive
FAIL Calling StylePropertyMap.getAll with a valid custom property returns a single element list with the correct entry assert_equals: expected "CSSUnparsedValue" but got "CSSStyleValue"
PASS Calling StylePropertyMap.getAll with a list-valued property returns all the values
Harness: the test ran to completion.
...@@ -23,8 +23,7 @@ CSSStyleValueVector ParseCSSStyleValue( ...@@ -23,8 +23,7 @@ CSSStyleValueVector ParseCSSStyleValue(
ExceptionState& exception_state) { ExceptionState& exception_state) {
const CSSPropertyID property_id = cssPropertyID(property_name); const CSSPropertyID property_id = cssPropertyID(property_name);
// TODO(775804): Handle custom properties if (property_id == CSSPropertyInvalid) {
if (property_id == CSSPropertyInvalid || property_id == CSSPropertyVariable) {
exception_state.ThrowTypeError("Invalid property name"); exception_state.ThrowTypeError("Invalid property name");
return CSSStyleValueVector(); return CSSStyleValueVector();
} }
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "core/css/cssom/CSSUnparsedValue.h" #include "core/css/cssom/CSSUnparsedValue.h"
#include "core/css/CSSVariableData.h"
#include "core/css/CSSVariableReferenceValue.h"
#include "core/css/cssom/CSSStyleVariableReferenceValue.h" #include "core/css/cssom/CSSStyleVariableReferenceValue.h"
#include "core/css/parser/CSSTokenizer.h" #include "core/css/parser/CSSTokenizer.h"
#include "platform/wtf/text/StringBuilder.h" #include "platform/wtf/text/StringBuilder.h"
...@@ -65,9 +67,13 @@ HeapVector<StringOrCSSVariableReferenceValue> ParserTokenRangeToTokens( ...@@ -65,9 +67,13 @@ HeapVector<StringOrCSSVariableReferenceValue> ParserTokenRangeToTokens(
} // namespace } // namespace
CSSUnparsedValue* CSSUnparsedValue::FromCSSValue( CSSUnparsedValue* CSSUnparsedValue::FromCSSValue(
const CSSVariableReferenceValue& css_variable_reference_value) { const CSSVariableReferenceValue& value) {
return CSSUnparsedValue::Create(ParserTokenRangeToTokens( DCHECK(value.VariableDataValue());
css_variable_reference_value.VariableDataValue()->TokenRange())); return FromCSSValue(*value.VariableDataValue());
}
CSSUnparsedValue* CSSUnparsedValue::FromCSSValue(const CSSVariableData& value) {
return CSSUnparsedValue::Create(ParserTokenRangeToTokens(value.TokenRange()));
} }
const CSSValue* CSSUnparsedValue::ToCSSValue( const CSSValue* CSSUnparsedValue::ToCSSValue(
......
...@@ -7,12 +7,14 @@ ...@@ -7,12 +7,14 @@
#include "base/macros.h" #include "base/macros.h"
#include "bindings/core/v8/string_or_css_variable_reference_value.h" #include "bindings/core/v8/string_or_css_variable_reference_value.h"
#include "core/css/CSSVariableReferenceValue.h"
#include "core/css/cssom/CSSStyleValue.h" #include "core/css/cssom/CSSStyleValue.h"
#include "platform/wtf/Vector.h" #include "platform/wtf/Vector.h"
namespace blink { namespace blink {
class CSSVariableReferenceValue;
class CSSVariableData;
class CORE_EXPORT CSSUnparsedValue final : public CSSStyleValue { class CORE_EXPORT CSSUnparsedValue final : public CSSStyleValue {
DEFINE_WRAPPERTYPEINFO(); DEFINE_WRAPPERTYPEINFO();
...@@ -23,6 +25,7 @@ class CORE_EXPORT CSSUnparsedValue final : public CSSStyleValue { ...@@ -23,6 +25,7 @@ class CORE_EXPORT CSSUnparsedValue final : public CSSStyleValue {
} }
static CSSUnparsedValue* FromCSSValue(const CSSVariableReferenceValue&); static CSSUnparsedValue* FromCSSValue(const CSSVariableReferenceValue&);
static CSSUnparsedValue* FromCSSValue(const CSSVariableData&);
const CSSValue* ToCSSValue(SecureContextMode) const override; const CSSValue* ToCSSValue(SecureContextMode) const override;
......
...@@ -4,8 +4,10 @@ ...@@ -4,8 +4,10 @@
#include "core/css/cssom/StyleValueFactory.h" #include "core/css/cssom/StyleValueFactory.h"
#include "core/css/CSSCustomPropertyDeclaration.h"
#include "core/css/CSSImageValue.h" #include "core/css/CSSImageValue.h"
#include "core/css/CSSValue.h" #include "core/css/CSSValue.h"
#include "core/css/CSSVariableReferenceValue.h"
#include "core/css/cssom/CSSKeywordValue.h" #include "core/css/cssom/CSSKeywordValue.h"
#include "core/css/cssom/CSSNumericValue.h" #include "core/css/cssom/CSSNumericValue.h"
#include "core/css/cssom/CSSOMTypes.h" #include "core/css/cssom/CSSOMTypes.h"
...@@ -44,6 +46,12 @@ CSSStyleValue* CreateStyleValue(const CSSValue& value) { ...@@ -44,6 +46,12 @@ CSSStyleValue* CreateStyleValue(const CSSValue& value) {
return CSSNumericValue::FromCSSValue(ToCSSPrimitiveValue(value)); return CSSNumericValue::FromCSSValue(ToCSSPrimitiveValue(value));
if (value.IsVariableReferenceValue()) if (value.IsVariableReferenceValue())
return CSSUnparsedValue::FromCSSValue(ToCSSVariableReferenceValue(value)); return CSSUnparsedValue::FromCSSValue(ToCSSVariableReferenceValue(value));
if (value.IsCustomPropertyDeclaration()) {
const CSSVariableData* variable_data =
ToCSSCustomPropertyDeclaration(value).Value();
DCHECK(variable_data);
return CSSUnparsedValue::FromCSSValue(*variable_data);
}
if (value.IsImageValue()) { if (value.IsImageValue()) {
return CSSURLImageValue::Create(ToCSSImageValue(value).Clone()); return CSSURLImageValue::Create(ToCSSImageValue(value).Clone());
} }
...@@ -73,12 +81,15 @@ const CSSValue* ParseProperty(CSSPropertyID property_id, ...@@ -73,12 +81,15 @@ const CSSValue* ParseProperty(CSSPropertyID property_id,
const auto tokens = tokenizer.TokenizeToEOF(); const auto tokens = tokenizer.TokenizeToEOF();
const CSSParserTokenRange range(tokens); const CSSParserTokenRange range(tokens);
if (const CSSValue* value = if (property_id != CSSPropertyVariable) {
CSSPropertyParser::ParseSingleValue(property_id, range, context)) { if (const CSSValue* value =
return value; CSSPropertyParser::ParseSingleValue(property_id, range, context)) {
return value;
}
} }
if (CSSVariableParser::ContainsValidVariableReferences(range)) { if (property_id == CSSPropertyVariable ||
CSSVariableParser::ContainsValidVariableReferences(range)) {
return CSSVariableReferenceValue::Create( return CSSVariableReferenceValue::Create(
CSSVariableData::Create(range, false /* is_animation_tainted */, CSSVariableData::Create(range, false /* is_animation_tainted */,
false /* needs variable resolution */), false /* needs variable resolution */),
...@@ -97,11 +108,6 @@ CSSStyleValueVector StyleValueFactory::FromString( ...@@ -97,11 +108,6 @@ CSSStyleValueVector StyleValueFactory::FromString(
DCHECK_NE(property_id, CSSPropertyInvalid); DCHECK_NE(property_id, CSSPropertyInvalid);
DCHECK(!CSSProperty::Get(property_id).IsShorthand()); DCHECK(!CSSProperty::Get(property_id).IsShorthand());
// TODO(775804): Handle custom properties
if (property_id == CSSPropertyVariable) {
return CSSStyleValueVector();
}
const CSSValue* value = ParseProperty(property_id, css_text, parser_context); const CSSValue* value = ParseProperty(property_id, css_text, parser_context);
if (!value) if (!value)
return CSSStyleValueVector(); return CSSStyleValueVector();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment