Commit 797edda2 authored by Darren Shen's avatar Darren Shen Committed by Commit Bot

[css-typed-om] Implement CSSStyleValue.parseAll.

CSSStyleValue.parseAll is similar to CSSStyleValue.parse in that it
converts a string value into a CSSStyleValue. The main difference is
how it handles list-valued properties.

Spec: https://drafts.css-houdini.org/css-typed-om-1/#dom-cssstylevalue-parseall

To reduce duplication, we move the common logic between parse and
parseAll into a helper function.

We also change the tests for parseAll because they wrongly expected that
parseAll return a CSSStyleValue instead of a sequence of CSSStyleValues.

Bug: 775802
Change-Id: I4b6b05d3a164e34709839ca2e059ec3fbf18a993
Reviewed-on: https://chromium-review.googlesource.com/742822
Commit-Queue: Darren Shen <shend@chromium.org>
Reviewed-by: default avatarnainar <nainar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#513054}
parent 6f337bcc
...@@ -3,17 +3,17 @@ PASS Calling CSSStyleValue.parse with an empty string throws a TypeError ...@@ -3,17 +3,17 @@ 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 an unsupported CSS property throws a TypeError
PASS Calling CSSStyleValue.parse with a CSS shorthand 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.parse 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 an empty string throws a TypeError 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 an unsupported CSS property throws a TypeError
PASS Calling CSSStyleValue.parseAll with a CSS shorthand throws a TypeError PASS Calling CSSStyleValue.parseAll with a CSS shorthand throws a TypeError
FAIL Calling CSSStyleValue.parseAll with an invalid cssText for the given property throws a SyntaxError assert_throws: function "() => CSSStyleValue[parseMethod]('width', '10deg')" threw object "TypeError: CSSStyleValue[parseMethod] is not a function" ("TypeError") expected object "SyntaxError" ("SyntaxError") PASS Calling CSSStyleValue.parseAll with an invalid cssText for the given property throws a SyntaxError
FAIL Calling CSSStyleValue.parseAll with a valid cssText for the given property returns a valid CSSStyleValue CSSStyleValue[parseMethod] is not a function PASS Calling CSSStyleValue.parse with a valid cssText for the given property returns a valid CSSStyleValue
FAIL Calling CSSStyleValue.parseAll with a mixed case cssText returns a valid CSSStyleValue CSSStyleValue[parseMethod] is not a function PASS Calling CSSStyleValue.parse with a mixed case cssText returns a valid CSSStyleValue
FAIL Calling CSSStyleValue.parseAll with a custom property returns a valid CSSStyleValue CSSStyleValue[parseMethod] is not a function 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.parse with a list-value property returns first list value
FAIL Calling CSSStyleValue.parseAll with a list-value property returns a sequence of values CSSStyleValue.parseAll is not a function PASS Calling CSSStyleValue.parseAll with a list-value property returns a sequence of values
Harness: the test ran to completion. Harness: the test ran to completion.
...@@ -25,21 +25,26 @@ for (const parseMethod of ['parse', 'parseAll']) { ...@@ -25,21 +25,26 @@ for (const parseMethod of ['parse', 'parseAll']) {
test(() => { test(() => {
assert_throws(new SyntaxError(), () => CSSStyleValue[parseMethod]('width', '10deg')); assert_throws(new SyntaxError(), () => CSSStyleValue[parseMethod]('width', '10deg'));
}, 'Calling CSSStyleValue.' + parseMethod + ' with an invalid cssText for the given property throws a SyntaxError'); }, 'Calling CSSStyleValue.' + parseMethod + ' with an invalid cssText for the given property throws a SyntaxError');
}
test(() => { const gValidNonListTests = [
const result = CSSStyleValue[parseMethod]('width', '10px'); { property: 'width', value: '10px', expected: CSS.px(10), desc: 'a valid cssText for the given property' },
assert_style_value_equals(result, CSS.px(10)); { property: 'wIdTh', value: '10px', expected: CSS.px(10), desc: 'a mixed case cssText' },
}, 'Calling CSSStyleValue.' + parseMethod + ' with a valid cssText for the given property returns a valid CSSStyleValue'); { property: '--foo', value: '10%', expected: CSS.percent(10), desc: 'a custom property' },
];
for (const {property, value, expected, desc} of gValidNonListTests) {
test(() => { test(() => {
const result = CSSStyleValue[parseMethod]('wIdTh', '10px'); const result = CSSStyleValue.parse(property, value);
assert_style_value_equals(result, CSS.px(10)); assert_style_value_equals(result, expected);
}, 'Calling CSSStyleValue.' + parseMethod + ' with a mixed case cssText returns a valid CSSStyleValue'); }, 'Calling CSSStyleValue.parse with ' + desc + ' returns a valid CSSStyleValue');
}
for (const {property, value, expected, desc} of gValidNonListTests) {
test(() => { test(() => {
const result = CSSStyleValue[parseMethod]('--foo', '10%'); const result = CSSStyleValue.parseAll(property, value);
assert_style_value_equals(result, CSS.percent(10)); assert_style_value_array_equals(result, [expected]);
}, 'Calling CSSStyleValue.' + parseMethod + ' with a custom property returns a valid CSSStyleValue'); }, 'Calling CSSStyleValue.parseAll with ' + desc + ' returns a single-element list containing a valid CSSStyleValue');
} }
test(() => { test(() => {
......
...@@ -794,6 +794,7 @@ interface CSSStyleSheet : StyleSheet ...@@ -794,6 +794,7 @@ interface CSSStyleSheet : StyleSheet
method removeRule method removeRule
interface CSSStyleValue interface CSSStyleValue
static method parse static method parse
static method parseAll
attribute @@toStringTag attribute @@toStringTag
method constructor method constructor
method toString method toString
......
...@@ -13,25 +13,23 @@ ...@@ -13,25 +13,23 @@
namespace blink { namespace blink {
ScriptValue CSSStyleValue::parse(ScriptState* script_state, namespace {
const String& property_name,
const String& value, CSSStyleValueVector ParseCSSStyleValue(const String& property_name,
ExceptionState& exception_state) { const String& value,
if (property_name.IsEmpty()) { ExceptionState& exception_state) {
exception_state.ThrowTypeError("Property name cannot be empty"); const CSSPropertyID property_id = cssPropertyID(property_name);
return ScriptValue::CreateNull(script_state);
}
CSSPropertyID property_id = cssPropertyID(property_name); // TODO(775804): Handle custom properties
// TODO(timloh): Handle custom properties
if (property_id == CSSPropertyInvalid || property_id == CSSPropertyVariable) { if (property_id == CSSPropertyInvalid || property_id == CSSPropertyVariable) {
exception_state.ThrowTypeError("Invalid property name"); exception_state.ThrowTypeError("Invalid property name");
return ScriptValue::CreateNull(script_state); return CSSStyleValueVector();
} }
if (isShorthandProperty(property_id)) { if (isShorthandProperty(property_id)) {
exception_state.ThrowTypeError( exception_state.ThrowTypeError(
"Parsing shorthand properties is not supported"); "Parsing shorthand properties is not supported");
return ScriptValue::CreateNull(script_state); return CSSStyleValueVector();
} }
const CSSValue* css_value = const CSSValue* css_value =
...@@ -41,17 +39,38 @@ ScriptValue CSSStyleValue::parse(ScriptState* script_state, ...@@ -41,17 +39,38 @@ ScriptValue CSSStyleValue::parse(ScriptState* script_state,
kSyntaxError, "The value provided ('" + value + kSyntaxError, "The value provided ('" + value +
"') could not be parsed as a '" + property_name + "') could not be parsed as a '" + property_name +
"'."); "'.");
return ScriptValue::CreateNull(script_state); return CSSStyleValueVector();
} }
CSSStyleValueVector style_value_vector = CSSStyleValueVector style_value_vector =
StyleValueFactory::CssValueToStyleValueVector(property_id, *css_value); StyleValueFactory::CssValueToStyleValueVector(property_id, *css_value);
DCHECK(!style_value_vector.IsEmpty()); DCHECK(!style_value_vector.IsEmpty());
return style_value_vector;
}
} // namespace
CSSStyleValue* CSSStyleValue::parse(const String& property_name,
const String& value,
ExceptionState& exception_state) {
CSSStyleValueVector style_value_vector =
ParseCSSStyleValue(property_name, value, exception_state);
if (style_value_vector.IsEmpty())
return nullptr;
return style_value_vector[0];
}
Nullable<CSSStyleValueVector> CSSStyleValue::parseAll(
const String& property_name,
const String& value,
ExceptionState& exception_state) {
CSSStyleValueVector style_value_vector =
ParseCSSStyleValue(property_name, value, exception_state);
if (style_value_vector.IsEmpty())
return nullptr;
v8::Local<v8::Value> wrapped_value = return style_value_vector;
ToV8(style_value_vector[0], script_state->GetContext()->Global(),
script_state->GetIsolate());
return ScriptValue(script_state, wrapped_value);
} }
String CSSStyleValue::StyleValueTypeToString(StyleValueType type) { String CSSStyleValue::StyleValueTypeToString(StyleValueType type) {
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef CSSStyleValue_h #ifndef CSSStyleValue_h
#define CSSStyleValue_h #define CSSStyleValue_h
#include "bindings/core/v8/Nullable.h"
#include "core/CSSPropertyNames.h" #include "core/CSSPropertyNames.h"
#include "core/CoreExport.h" #include "core/CoreExport.h"
#include "core/css/CSSValue.h" #include "core/css/CSSValue.h"
...@@ -14,8 +15,9 @@ ...@@ -14,8 +15,9 @@
namespace blink { namespace blink {
class ExceptionState; class ExceptionState;
class ScriptState;
class ScriptValue; class CSSStyleValue;
using CSSStyleValueVector = HeapVector<Member<CSSStyleValue>>;
// The base class for all CSS values returned by the Typed OM. // The base class for all CSS values returned by the Typed OM.
// See CSSStyleValue.idl for additional documentation about this class. // See CSSStyleValue.idl for additional documentation about this class.
...@@ -48,10 +50,12 @@ class CORE_EXPORT CSSStyleValue : public ScriptWrappable { ...@@ -48,10 +50,12 @@ class CORE_EXPORT CSSStyleValue : public ScriptWrappable {
kInvalidType, kInvalidType,
}; };
static ScriptValue parse(ScriptState*, static CSSStyleValue* parse(const String& property_name,
const String& property_name, const String& value,
const String& value, ExceptionState&);
ExceptionState&); static Nullable<CSSStyleValueVector> parseAll(const String& property_name,
const String& value,
ExceptionState&);
virtual ~CSSStyleValue() {} virtual ~CSSStyleValue() {}
...@@ -75,8 +79,6 @@ class CORE_EXPORT CSSStyleValue : public ScriptWrappable { ...@@ -75,8 +79,6 @@ class CORE_EXPORT CSSStyleValue : public ScriptWrappable {
CSSStyleValue() {} CSSStyleValue() {}
}; };
typedef HeapVector<Member<CSSStyleValue>> CSSStyleValueVector;
} // namespace blink } // namespace blink
#endif #endif
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
Exposed(Window CSSTypedOM, PaintWorklet CSSPaintAPI) Exposed(Window CSSTypedOM, PaintWorklet CSSPaintAPI)
] interface CSSStyleValue { ] interface CSSStyleValue {
stringifier; stringifier;
// TODO(meade): Should be (CSSStyleValue or sequence<CSSStyleValue>)? instead of object?. Fix when the code generator supports this.
// Putting Exposed=Window in the next line makes |parse| not exposed to PaintWorklet. // Putting Exposed=Window in the next line makes |parse| not exposed to PaintWorklet.
[RaisesException, CallWith=ScriptState, Exposed=Window] static object? parse(DOMString property, DOMString cssText); [RaisesException, Exposed=Window] static CSSStyleValue? parse(DOMString property, DOMString cssText);
[RaisesException, Exposed=Window] static sequence<CSSStyleValue>? parseAll(DOMString property, DOMString cssText);
}; };
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