Commit b786c57c authored by Anders Hartvoll Ruud's avatar Anders Hartvoll Ruud Committed by Commit Bot

[css-properties-values-api] Support CSSStyleValues in StylePropertyMap.set.

In StyleValueToCSSValue, when checking whether a certain CSSStyleValue
matches the property in question, we now ask the registration (via
CSSOMTypes) if the CSSStyleValue matches. If it doesn't match, we throw
a TypeError like for normal properties. If it does match, the CSSStyleValue
is stringified, tokenized, and set on the style rule as tokens.

I have postponed support for <color> and <transform-function>, because
CSSUnsupportedStyleValue currently does not handle registered custom
properties at all. This is appropriate to fix in a separate CL.

Note that, because the string version of StylePropertyMap.set also uses
StyleValueToCSSValue, it will no longer be possible to set registered
custom properties with a string--even if the syntax is matched.
A subsequent CL will fix this.

R=futhark@chromium.org

Bug: 641877
Change-Id: Ie0cc2f87e39f8f59015824bfd1b81efaf402c326
Reviewed-on: https://chromium-review.googlesource.com/1175822
Commit-Queue: Anders Ruud <andruud@chromium.org>
Reviewed-by: default avatarRune Lillesveen <futhark@chromium.org>
Cr-Commit-Position: refs/heads/master@{#583695}
parent ecdb6a3b
<!DOCTYPE html>
<link rel="author" title="Anders Hartvoll Ruud" href="andruud@chromium.org">
<!-- TODO(andruud): Add Typed OM details to spec and link to it here. -->
<link rel="help" href="https://drafts.css-houdini.org/css-properties-values-api-1/#supported-syntax-strings" />
<link rel="help" href="https://github.com/w3c/css-houdini-drafts/pull/783" />
<meta name="assert" content="Verifies that registered custom properties interact correctly with CSS Typed OM" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style id=style>
div {}
</style>
<div id=target></div>
<script>
......@@ -43,7 +45,7 @@ function assert_computed_type(name, value, expected) {
}
if (value != null) {
target.attributeStyleMap.set(name, value);
target.style = `${name}: ${value}`;
}
let computedValue = target.computedStyleMap().get(name);
......@@ -52,7 +54,7 @@ function assert_computed_type(name, value, expected) {
assert_true(computedValue instanceof expected);
if (value != null) {
target.attributeStyleMap.delete(name);
target.style = '';
}
}
......@@ -177,7 +179,7 @@ test(function(){
assert_equals(target.computedStyleMap().getAll(name).length, 2);
assert_true(target.computedStyleMap().getAll(name).every(x => x instanceof CSSUnitValue));
target.attributeStyleMap.set(name, '10px 20px 30px');
target.style = `${name}: 10px 20px 30px`;
assert_equals(target.computedStyleMap().getAll(name).length, 3);
assert_true(target.computedStyleMap().getAll(name).every(x => x instanceof CSSUnitValue));
}, 'All computed values correctly reified in space-separated list');
......@@ -187,7 +189,7 @@ test(function(){
assert_equals(target.computedStyleMap().getAll(name).length, 2);
assert_true(target.computedStyleMap().getAll(name).every(x => x instanceof CSSUnitValue));
target.attributeStyleMap.set(name, '10px, 20px, 30px');
target.style = `${name}: 10px, 20px, 30px`;
assert_equals(target.computedStyleMap().getAll(name).length, 3);
assert_true(target.computedStyleMap().getAll(name).every(x => x instanceof CSSUnitValue));
}, 'All computed values correctly reified in comma-separated list');
......@@ -285,7 +287,7 @@ test(function(){
test(function(){
let name = gen_prop('<length>+', '0px');
target.attributeStyleMap.clear();
target.attributeStyleMap.set(name, '10px 20px 30px');
target.style = `${name}: 10px 20px 30px`;
assert_equals(target.attributeStyleMap.getAll(name).length, 3);
assert_true(target.attributeStyleMap.getAll(name).every(x => x instanceof CSSUnitValue));
}, 'attributeStyleMap.getAll returns a list of CSSUnitValues for <length>+');
......@@ -293,9 +295,145 @@ test(function(){
test(function(){
let name = gen_prop('<length>#', '0px');
target.attributeStyleMap.clear();
target.attributeStyleMap.set(name, '10px, 20px, 30px');
target.style = `${name}: 10px, 20px, 30px`;
assert_equals(target.attributeStyleMap.getAll(name).length, 3);
assert_true(target.attributeStyleMap.getAll(name).every(x => x instanceof CSSUnitValue));
}, 'attributeStyleMap.getAll returns a list of CSSUnitValues for <length>#');
// StylePropertyMap.set
function test_style_property_map_set_using_property_map(propertyMapName, propertyMap, options) {
test(function(){
let name = gen_prop(options.syntax, options.initialValue);
propertyMap.clear();
for (let value of options.shouldAccept)
propertyMap.set(name, value);
for (let value of options.shouldReject) {
assert_throws(new TypeError(), () => propertyMap.set(name, value));
}
}, `${propertyMapName}.set accepts correct CSSUnitValues for ${options.syntax}`);
}
// Verify that the correct CSSStyleValues are accepted/rejected for a registered
// property with the specified syntax.
//
// The same test is performed twice: once for attributeStyleMap, and once
// for styleMap.
function test_style_property_map_set(options) {
test_style_property_map_set_using_property_map('attributeStyleMap', target.attributeStyleMap, options);
test_style_property_map_set_using_property_map('styleMap', style.sheet.rules[0].styleMap, options);
}
let unparsed = x => new CSSUnparsedValue([x]);
let keyword = x => new CSSKeywordValue(x);
let sum = (a, b) => new CSSMathSum(a, b);
let url_image = x => CSSStyleValue.parse('background-image', x);
test_style_property_map_set({
syntax: '*',
initialValue: 'none',
shouldAccept: [unparsed('thing')],
shouldReject: [CSS.px(15), keyword('none')],
});
test_style_property_map_set({
syntax: '<angle>',
initialValue: '0deg',
shouldAccept: [CSS.deg(42), CSS.turn(2)],
shouldReject: [unparsed('42deg'), CSS.px(15)],
});
test_style_property_map_set({
syntax: '<custom-ident>',
initialValue: 'none',
shouldAccept: [keyword('foo')],
shouldReject: [unparsed('foo'), CSS.px(15)],
});
test_style_property_map_set({
syntax: '<image>',
initialValue: 'url(a)',
shouldAccept: [url_image('url(b)')],
shouldReject: [unparsed('url(b)'), CSS.px(100)],
});
test_style_property_map_set({
syntax: '<integer>',
initialValue: '0',
shouldAccept: [CSS.number(1), CSS.number(-42)],
shouldReject: [unparsed('42'), CSS.px(100)],
});
test_style_property_map_set({
syntax: '<length-percentage>',
initialValue: '0px',
shouldAccept: [CSS.percent(10), CSS.px(1), CSS.em(1)],
shouldReject: [unparsed('10%'), unparsed('10px'), CSS.dpi(1)],
});
test_style_property_map_set({
syntax: '<length>',
initialValue: '0px',
shouldAccept: [CSS.px(10), CSS.em(10), CSS.vh(200), sum(CSS.px(10), CSS.em(20))],
shouldReject: [unparsed('10px'), CSS.percent(1)],
});
test_style_property_map_set({
syntax: '<number>',
initialValue: '0',
shouldAccept: [CSS.number(1337), CSS.number(-42.5)],
shouldReject: [unparsed('42'), CSS.px(15)],
});
test_style_property_map_set({
syntax: '<percentage>',
initialValue: '0%',
shouldAccept: [CSS.percent(10)],
shouldReject: [unparsed('10%'), CSS.px(1)],
});
test_style_property_map_set({
syntax: '<resolution>',
initialValue: '0dpi',
shouldAccept: [CSS.dpi(100), CSS.dpcm(10), CSS.dppx(50)],
shouldReject: [unparsed('42'), CSS.px(15)],
});
test_style_property_map_set({
syntax: '<time>',
initialValue: '0s',
shouldAccept: [CSS.s(42), CSS.ms(16)],
shouldReject: [unparsed('42s'), CSS.px(15)],
});
test_style_property_map_set({
syntax: '<url>',
initialValue: 'url(a)',
shouldAccept: [url_image('url(b)')],
shouldReject: [unparsed('url(b)'), CSS.px(100)],
});
test_style_property_map_set({
syntax: '<transform-list>',
initialValue: 'translateX(0px)',
shouldAccept: [CSSStyleValue.parse('transform', 'translateX(10px)')],
shouldReject: [unparsed('transformX(10px'), CSS.px(100)],
});
test_style_property_map_set({
syntax: 'none | thing | THING',
initialValue: 'none',
shouldAccept: [keyword('thing'), keyword('THING')],
shouldReject: [unparsed('thing'), CSS.px(15), keyword('notathing')],
});
test_style_property_map_set({
syntax: '<angle> | <length>',
initialValue: '0deg',
shouldAccept: [CSS.deg(42), CSS.turn(2), CSS.px(10), CSS.em(10)],
shouldReject: [unparsed('42deg'), unparsed('20px'), CSS.s(1)],
});
</script>
......@@ -7,73 +7,77 @@
#include "third_party/blink/renderer/core/css/cssom/cssom_types.h"
#include "third_party/blink/renderer/core/css/cssom/cssom_keywords.h"
#include "third_party/blink/renderer/core/css/cssom/css_keyword_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_numeric_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_style_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_unsupported_style_value.h"
#include "third_party/blink/renderer/core/css/cssom/cssom_keywords.h"
#include "third_party/blink/renderer/core/css/properties/css_property.h"
#include "third_party/blink/renderer/core/css/property_registration.h"
namespace blink {
namespace {
bool IsCSSStyleValueLength(const CSSStyleValue& value) {
bool CSSOMTypes::IsCSSStyleValueLength(const CSSStyleValue& value) {
if (!value.IsNumericValue())
return false;
return static_cast<const CSSNumericValue&>(value).Type().
MatchesBaseType(CSSNumericValueType::BaseType::kLength);
}
bool IsCSSStyleValueNumber(const CSSStyleValue& value) {
bool CSSOMTypes::IsCSSStyleValueNumber(const CSSStyleValue& value) {
if (!value.IsNumericValue())
return false;
return static_cast<const CSSNumericValue&>(value).Type().
MatchesNumber();
}
bool IsCSSStyleValueTime(const CSSStyleValue& value) {
bool CSSOMTypes::IsCSSStyleValueTime(const CSSStyleValue& value) {
if (!value.IsNumericValue())
return false;
return static_cast<const CSSNumericValue&>(value).Type().
MatchesBaseType(CSSNumericValueType::BaseType::kTime);
}
bool IsCSSStyleValueAngle(const CSSStyleValue& value) {
bool CSSOMTypes::IsCSSStyleValueAngle(const CSSStyleValue& value) {
if (!value.IsNumericValue())
return false;
return static_cast<const CSSNumericValue&>(value).Type().
MatchesBaseType(CSSNumericValueType::BaseType::kAngle);
}
bool IsCSSStyleValuePercentage(const CSSStyleValue& value) {
bool CSSOMTypes::IsCSSStyleValuePercentage(const CSSStyleValue& value) {
if (!value.IsNumericValue())
return false;
return static_cast<const CSSNumericValue&>(value).Type().
MatchesPercentage();
}
bool IsCSSStyleValueFlex(const CSSStyleValue& value) {
bool CSSOMTypes::IsCSSStyleValueResolution(const CSSStyleValue& value) {
if (!value.IsNumericValue())
return false;
return static_cast<const CSSNumericValue&>(value).Type().
MatchesBaseType(CSSNumericValueType::BaseType::kResolution);
}
bool CSSOMTypes::IsCSSStyleValueFlex(const CSSStyleValue& value) {
if (!value.IsNumericValue())
return false;
return static_cast<const CSSNumericValue&>(value).Type().
MatchesBaseType(CSSNumericValueType::BaseType::kFlex);
}
bool IsCSSStyleValueImage(const CSSStyleValue& value) {
bool CSSOMTypes::IsCSSStyleValueImage(const CSSStyleValue& value) {
return value.GetType() == CSSStyleValue::kURLImageType;
}
bool IsCSSStyleValueTransform(const CSSStyleValue& value) {
bool CSSOMTypes::IsCSSStyleValueTransform(const CSSStyleValue& value) {
return value.GetType() == CSSStyleValue::kTransformType;
}
bool IsCSSStyleValuePosition(const CSSStyleValue& value) {
bool CSSOMTypes::IsCSSStyleValuePosition(const CSSStyleValue& value) {
return value.GetType() == CSSStyleValue::kPositionType;
}
}
bool CSSOMTypes::IsPropertySupported(CSSPropertyID id) {
switch (id) {
case CSSPropertyVariable:
......@@ -87,7 +91,13 @@ bool CSSOMTypes::IsPropertySupported(CSSPropertyID id) {
}
bool CSSOMTypes::PropertyCanTake(CSSPropertyID id,
const PropertyRegistration* registration,
const CSSStyleValue& value) {
if (id == CSSPropertyVariable && registration) {
return registration->Syntax().CanTake(value);
}
if (value.GetType() == CSSStyleValue::kKeywordType) {
return CSSOMKeywords::ValidKeywordForProperty(
id, ToCSSKeywordValue(value));
......@@ -107,7 +117,7 @@ bool CSSOMTypes::PropertyCanTake(CSSPropertyID id,
case {{property.property_id}}:
return (
{% for type in property.typedom_types if type != 'Keyword' %}
{{ "|| " if not loop.first }}IsCSSStyleValue{{type}}(value)
{{ "|| " if not loop.first }}CSSOMTypes::IsCSSStyleValue{{type}}(value)
{% endfor %}
);
{% endif %}
......
......@@ -8,6 +8,9 @@
#include "third_party/blink/renderer/core/css/css_uri_value.h"
#include "third_party/blink/renderer/core/css/css_value_list.h"
#include "third_party/blink/renderer/core/css/css_variable_reference_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_keyword_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_style_value.h"
#include "third_party/blink/renderer/core/css/cssom/cssom_types.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_idioms.h"
#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
#include "third_party/blink/renderer/core/css/parser/css_variable_parser.h"
......@@ -223,6 +226,64 @@ const CSSValue* ConsumeSyntaxComponent(const CSSSyntaxComponent& syntax,
return result;
}
bool CSSSyntaxComponent::CanTake(const CSSStyleValue& value) const {
switch (type_) {
case CSSSyntaxType::kTokenStream:
return value.GetType() == CSSStyleValue::kUnparsedType;
case CSSSyntaxType::kIdent:
return value.GetType() == CSSStyleValue::kKeywordType &&
static_cast<const CSSKeywordValue&>(value).value() == string_;
case CSSSyntaxType::kLength:
return CSSOMTypes::IsCSSStyleValueLength(value);
case CSSSyntaxType::kInteger:
// TODO(andruud): Support rounding.
// https://drafts.css-houdini.org/css-typed-om-1/#numeric-objects
FALLTHROUGH;
case CSSSyntaxType::kNumber:
return CSSOMTypes::IsCSSStyleValueNumber(value);
case CSSSyntaxType::kPercentage:
return CSSOMTypes::IsCSSStyleValuePercentage(value);
case CSSSyntaxType::kLengthPercentage:
// TODO(andruud): Support calc(X% + Ypx).
return CSSOMTypes::IsCSSStyleValueLength(value) ||
CSSOMTypes::IsCSSStyleValuePercentage(value);
case CSSSyntaxType::kColor:
// TODO(andruud): Support custom properties in CSSUnsupportedStyleValue.
return false;
case CSSSyntaxType::kImage:
case CSSSyntaxType::kUrl:
return value.GetType() == CSSStyleValue::kURLImageType;
case CSSSyntaxType::kAngle:
return CSSOMTypes::IsCSSStyleValueAngle(value);
case CSSSyntaxType::kTime:
return CSSOMTypes::IsCSSStyleValueTime(value);
case CSSSyntaxType::kResolution:
return CSSOMTypes::IsCSSStyleValueResolution(value);
case CSSSyntaxType::kTransformFunction:
// TODO(andruud): Currently not supported by Typed OM.
// https://github.com/w3c/css-houdini-drafts/issues/290
// For now, this should accept a CSSUnsupportedStyleValue, such that
// <transform-function> values can be moved from one registered property
// to another.
// TODO(andruud): Support custom properties in CSSUnsupportedStyleValue.
return false;
case CSSSyntaxType::kTransformList:
return value.GetType() == CSSStyleValue::kTransformType;
case CSSSyntaxType::kCustomIdent:
return value.GetType() == CSSStyleValue::kKeywordType;
default:
return false;
}
}
bool CSSSyntaxDescriptor::CanTake(const CSSStyleValue& value) const {
for (const CSSSyntaxComponent& component : syntax_components_) {
if (component.CanTake(value))
return true;
}
return false;
}
const CSSValue* CSSSyntaxDescriptor::Parse(CSSParserTokenRange range,
const CSSParserContext* context,
bool is_animation_tainted) const {
......
......@@ -10,6 +10,7 @@
namespace blink {
class CSSParserContext;
class CSSStyleValue;
class CSSValue;
enum class CSSSyntaxType {
......@@ -45,6 +46,8 @@ struct CSSSyntaxComponent {
bool IsRepeatable() const { return repeat_ != CSSSyntaxRepeat::kNone; }
bool CanTake(const CSSStyleValue&) const;
CSSSyntaxType type_;
String string_; // Only used when type_ is CSSSyntaxType::kIdent
CSSSyntaxRepeat repeat_;
......@@ -57,6 +60,7 @@ class CORE_EXPORT CSSSyntaxDescriptor {
const CSSValue* Parse(CSSParserTokenRange,
const CSSParserContext*,
bool is_animation_tainted) const;
bool CanTake(const CSSStyleValue&) const;
bool IsValid() const { return !syntax_components_.IsEmpty(); }
bool IsTokenStream() const {
return syntax_components_.size() == 1 &&
......
......@@ -11,6 +11,8 @@
namespace blink {
class PropertyRegistration;
// This class provides utility functions for determining whether a property
// can accept a CSSStyleValue type or instance. Its implementation is generated
// using input from CSSProperties.json5 and the script
......@@ -19,9 +21,21 @@ class CSSOMTypes {
STATIC_ONLY(CSSOMTypes);
public:
static bool IsCSSStyleValueLength(const CSSStyleValue&);
static bool IsCSSStyleValueNumber(const CSSStyleValue&);
static bool IsCSSStyleValueTime(const CSSStyleValue&);
static bool IsCSSStyleValueAngle(const CSSStyleValue&);
static bool IsCSSStyleValuePercentage(const CSSStyleValue&);
static bool IsCSSStyleValueResolution(const CSSStyleValue&);
static bool IsCSSStyleValueFlex(const CSSStyleValue&);
static bool IsCSSStyleValueImage(const CSSStyleValue&);
static bool IsCSSStyleValueTransform(const CSSStyleValue&);
static bool IsCSSStyleValuePosition(const CSSStyleValue&);
static bool IsPropertySupported(CSSPropertyID);
static bool PropertyCanTake(CSSPropertyID, const CSSStyleValue&);
static bool PropertyCanTakeType(CSSPropertyID, CSSStyleValue::StyleValueType);
static bool PropertyCanTake(CSSPropertyID,
const PropertyRegistration*,
const CSSStyleValue&);
};
} // namespace blink
......
......@@ -12,7 +12,9 @@
#include "third_party/blink/renderer/core/css/cssom/style_value_factory.h"
#include "third_party/blink/renderer/core/css/parser/css_parser.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
#include "third_party/blink/renderer/core/css/parser/css_tokenizer.h"
#include "third_party/blink/renderer/core/css/properties/css_property.h"
#include "third_party/blink/renderer/core/css/property_registry.h"
#include "third_party/blink/renderer/core/style_property_shorthand.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
......@@ -38,10 +40,11 @@ CSSValueList* CssValueListForPropertyID(CSSPropertyID property_id) {
const CSSValue* StyleValueToCSSValue(
const CSSProperty& property,
const PropertyRegistration* registration,
const CSSStyleValue& style_value,
const ExecutionContext& execution_context) {
const CSSPropertyID property_id = property.PropertyID();
if (!CSSOMTypes::PropertyCanTake(property_id, style_value))
if (!CSSOMTypes::PropertyCanTake(property_id, registration, style_value))
return nullptr;
if (style_value.GetType() == CSSStyleValue::kUnknownType) {
......@@ -54,6 +57,17 @@ const CSSValue* StyleValueToCSSValue(
// TODO(https://crbug.com/545324): Move this into a method on
// CSSProperty when there are more of these cases.
switch (property_id) {
case CSSPropertyVariable:
if (registration &&
style_value.GetType() != CSSStyleValue::kUnparsedType) {
CSSTokenizer tokenizer(style_value.toString());
CSSParserTokenRange range(tokenizer.TokenizeToEOF());
CSSParserContext* context = CSSParserContext::Create(execution_context);
scoped_refptr<CSSVariableData> variable_data = CSSVariableData::Create(
range, false, false, context->BaseURL(), context->Charset());
return CSSVariableReferenceValue::Create(variable_data, *context);
}
break;
case CSSPropertyBorderBottomLeftRadius:
case CSSPropertyBorderBottomRightRadius:
case CSSPropertyBorderTopLeftRadius:
......@@ -179,6 +193,7 @@ const CSSValue* StyleValueToCSSValue(
const CSSValue* CoerceStyleValueOrString(
const CSSProperty& property,
const PropertyRegistration* registration,
const CSSStyleValueOrString& value,
const ExecutionContext& execution_context) {
DCHECK(!property.IsRepeated());
......@@ -187,8 +202,8 @@ const CSSValue* CoerceStyleValueOrString(
if (!value.GetAsCSSStyleValue())
return nullptr;
return StyleValueToCSSValue(property, *value.GetAsCSSStyleValue(),
execution_context);
return StyleValueToCSSValue(property, registration,
*value.GetAsCSSStyleValue(), execution_context);
} else {
DCHECK(value.IsString());
const auto values = StyleValueFactory::FromString(
......@@ -197,7 +212,8 @@ const CSSValue* CoerceStyleValueOrString(
if (values.size() != 1U)
return nullptr;
return StyleValueToCSSValue(property, *values[0], execution_context);
return StyleValueToCSSValue(property, registration, *values[0],
execution_context);
}
}
......@@ -218,7 +234,7 @@ const CSSValue* CoerceStyleValuesOrStrings(
return nullptr;
css_values.push_back(StyleValueToCSSValue(
property, *value.GetAsCSSStyleValue(), execution_context));
property, nullptr, *value.GetAsCSSStyleValue(), execution_context));
} else {
DCHECK(value.IsString());
if (!parser_context)
......@@ -231,8 +247,8 @@ const CSSValue* CoerceStyleValuesOrStrings(
for (const auto& subvalue : subvalues) {
DCHECK(subvalue);
css_values.push_back(
StyleValueToCSSValue(property, *subvalue, execution_context));
css_values.push_back(StyleValueToCSSValue(property, nullptr, *subvalue,
execution_context));
}
}
}
......@@ -273,8 +289,10 @@ void StylePropertyMap::set(const ExecutionContext* execution_context,
String css_text;
if (values[0].IsCSSStyleValue()) {
CSSStyleValue* style_value = values[0].GetAsCSSStyleValue();
if (style_value && CSSOMTypes::PropertyCanTake(property_id, *style_value))
if (style_value &&
CSSOMTypes::PropertyCanTake(property_id, nullptr, *style_value)) {
css_text = style_value->toString();
}
} else {
css_text = values[0].GetAsString();
}
......@@ -287,11 +305,23 @@ void StylePropertyMap::set(const ExecutionContext* execution_context,
return;
}
const PropertyRegistration* registration = nullptr;
if (property_id == CSSPropertyVariable && execution_context->IsDocument()) {
const PropertyRegistry* registry =
ToDocument(*execution_context).GetPropertyRegistry();
if (registry) {
registration = registry->Registration(AtomicString(property_name));
}
}
const CSSValue* result = nullptr;
if (property.IsRepeated())
if (property.IsRepeated()) {
result = CoerceStyleValuesOrStrings(property, values, *execution_context);
else if (values.size() == 1U)
result = CoerceStyleValueOrString(property, values[0], *execution_context);
} else if (values.size() == 1U) {
result = CoerceStyleValueOrString(property, registration, values[0],
*execution_context);
}
if (!result) {
exception_state.ThrowTypeError("Invalid type for property");
......
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