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

CSS Typed OM: Proper types for custom props during iteration.

Currently, you get CSSUnparsedValues when iterating entries on the
.computedStyleMap(), even for properties which are registered with a
type. However, if you do .computedStyleMap().get(...) with a registered
property, you _do_ get the correct type.

This is because ComputedStyleCSSValueMapping::Get properly looks up the
typed values on the ComputedStyle, but ::GetVariables does not; instead it
directly returns the CSSVariableData for everything, regardless of
registrations.

This patch changes the behavior of iteration to use the same code path
as .get(). This ensures that we either create a CSSCustomProperty-
Declaration on the fly for unregistered properties, or we re-use the
existing (and typed) CSSValue for registered properties.

Note: I initially wanted to do a nested iterator thing here, but dropped
      it because we would anyway need a temp HashSet to avoid potential
      duplicates from the StyleInheritedVariables-root.

Note: One caller of GetVariables() just wants the size. It's possibly a
      little overkill to create entire HashMap just to count something,
      but I don't want to resolve that here in the same patch.

R=futhark@chromium.org, haraken@chromium.org

Bug: 850072
Change-Id: I64bfb3cc22a377cf956420a9e64d47ca3daac1e2
Reviewed-on: https://chromium-review.googlesource.com/1090848Reviewed-by: default avatarRune Lillesveen <futhark@chromium.org>
Commit-Queue: Anders Ruud <andruud@chromium.org>
Cr-Commit-Position: refs/heads/master@{#565605}
parent db4d3abf
<!DOCTYPE>
<!DOCTYPE html>
<title>NoModificationAllowedError when mutating read only properties</title>
<link rel="author" title="Anders Hartvoll Ruud" href="andruud@chromium.org">
<link rel="help" href="https://www.w3.org/TR/cssom-1/#dom-cssstyledeclaration-setpropertyvalue">
......
......@@ -9,5 +9,6 @@ FAIL Getting a height with a calc type containing var values returns a CSSCalcVa
PASS Getting the value of a registered property that isn't set on the element returns the initial value for the property
PASS Getting the value of a property that isn't registered returns null
PASS getAll for a length type registered property returns a single value
PASS Inherited custom property produces correct type during iteration
Harness: the test ran to completion.
......@@ -140,6 +140,15 @@ test(function() {
assert_equals(result[0].toString(), '100px');
}, 'getAll for a length type registered property returns a single value');
test(function() {
var result = Array.from(computedStyleMap)
.filter(m => m[0] == '--my-inherited-length')
.flat(2);
assert_equals(result.length, 2);
assert_equals(result[1].constructor.name, CSSUnitValue.name);
assert_equals(result[1].toString(), '200px');
}, 'Inherited custom property produces correct type during iteration');
document.onreadystatechange = function() {
if(document.readyState == 'complete') {
t1Callback();
......
......@@ -57,13 +57,21 @@ const CSSValue* ComputedStyleCSSValueMapping::Get(
return CSSCustomPropertyDeclaration::Create(custom_property_name, data);
}
HashMap<AtomicString, scoped_refptr<CSSVariableData>>
ComputedStyleCSSValueMapping::GetVariables(const ComputedStyle& style) {
HeapHashMap<AtomicString, Member<const CSSValue>>
ComputedStyleCSSValueMapping::GetVariables(const ComputedStyle& style,
const PropertyRegistry* registry) {
HeapHashMap<AtomicString, Member<const CSSValue>> variables;
// TODO(timloh): Also return non-inherited variables
StyleInheritedVariables* variables = style.InheritedVariables();
if (variables)
return variables->GetVariables();
return {};
StyleInheritedVariables* inherited = style.InheritedVariables();
if (inherited) {
for (const auto& name : inherited->GetCustomPropertyNames()) {
const CSSValue* value =
ComputedStyleCSSValueMapping::Get(name, style, registry);
if (value)
variables.Set(name, value);
}
}
return variables;
}
} // namespace blink
......@@ -10,7 +10,6 @@
namespace blink {
class CSSVariableData;
class ComputedStyle;
class PropertyRegistry;
......@@ -21,8 +20,9 @@ class ComputedStyleCSSValueMapping {
static const CSSValue* Get(const AtomicString custom_property_name,
const ComputedStyle&,
const PropertyRegistry*);
static HashMap<AtomicString, scoped_refptr<CSSVariableData>> GetVariables(
const ComputedStyle&);
static HeapHashMap<AtomicString, Member<const CSSValue>> GetVariables(
const ComputedStyle& style,
const PropertyRegistry*);
};
} // namespace blink
......
......@@ -316,12 +316,14 @@ const CSSValue* CSSComputedStyleDeclaration::GetPropertyCSSValue(
StyledNode()->GetDocument().GetPropertyRegistry());
}
HashMap<AtomicString, scoped_refptr<CSSVariableData>>
HeapHashMap<AtomicString, Member<const CSSValue>>
CSSComputedStyleDeclaration::GetVariables() const {
const ComputedStyle* style = ComputeComputedStyle();
if (!style)
return {};
return ComputedStyleCSSValueMapping::GetVariables(*style);
DCHECK(StyledNode());
return ComputedStyleCSSValueMapping::GetVariables(
*style, StyledNode()->GetDocument().GetPropertyRegistry());
}
const CSSValue* CSSComputedStyleDeclaration::GetPropertyCSSValue(
......
......@@ -33,7 +33,6 @@
namespace blink {
class CSSVariableData;
class ExceptionState;
class LayoutObject;
class MutableCSSPropertyValueSet;
......@@ -61,7 +60,7 @@ class CORE_EXPORT CSSComputedStyleDeclaration final
const CSSValue* GetPropertyCSSValue(const CSSProperty&) const;
const CSSValue* GetPropertyCSSValue(AtomicString custom_property_name) const;
HashMap<AtomicString, scoped_refptr<CSSVariableData>> GetVariables() const;
HeapHashMap<AtomicString, Member<const CSSValue>> GetVariables() const;
const CSSValue* GetFontSizeCSSValuePreferringKeyword() const;
bool IsMonospaceFont() const;
......
......@@ -167,8 +167,11 @@ unsigned int ComputedStylePropertyMap::size() {
if (!style)
return 0;
DCHECK(StyledNode());
return CSSComputedStyleDeclaration::ComputableProperties().size() +
ComputedStyleCSSValueMapping::GetVariables(*style).size();
ComputedStyleCSSValueMapping::GetVariables(
*style, StyledNode()->GetDocument().GetPropertyRegistry())
.size();
}
bool ComputedStylePropertyMap::ComparePropertyNames(const String& a,
......@@ -263,13 +266,12 @@ void ComputedStylePropertyMap::ForEachProperty(
values.emplace_back(property->GetPropertyNameAtomicString(), value);
}
PropertyRegistry* registry =
StyledNode()->GetDocument().GetPropertyRegistry();
for (const auto& name_value :
ComputedStyleCSSValueMapping::GetVariables(*style)) {
if (name_value.value) {
values.emplace_back(name_value.key,
CSSCustomPropertyDeclaration::Create(
name_value.key, name_value.value));
}
ComputedStyleCSSValueMapping::GetVariables(*style, registry)) {
values.emplace_back(name_value.key, name_value.value);
}
std::sort(values.begin(), values.end(), [](const auto& a, const auto& b) {
......
......@@ -1157,11 +1157,9 @@ Response InspectorCSSAgent::getComputedStyleForNode(
}
for (const auto& it : computed_style_info->GetVariables()) {
if (!it.value)
continue;
(*style)->addItem(protocol::CSS::CSSComputedStyleProperty::create()
.setName(it.key)
.setValue(it.value->TokenRange().Serialize())
.setValue(it.value->CssText())
.build());
}
return Response::OK();
......
......@@ -74,16 +74,15 @@ void StyleInheritedVariables::RemoveVariable(const AtomicString& name) {
iterator->value = nullptr;
}
HashMap<AtomicString, scoped_refptr<CSSVariableData>>
StyleInheritedVariables::GetVariables() const {
HashSet<AtomicString> StyleInheritedVariables::GetCustomPropertyNames() const {
HashSet<AtomicString> names;
if (root_) {
HashMap<AtomicString, scoped_refptr<CSSVariableData>> result(root_->data_);
for (const auto& pair : data_)
result.Set(pair.key, pair.value);
return result;
} else {
return data_;
for (const auto& pair : root_->data_)
names.insert(pair.key);
}
for (const auto& pair : data_)
names.insert(pair.key);
return names;
}
} // namespace blink
......@@ -39,10 +39,10 @@ class StyleInheritedVariables : public RefCounted<StyleInheritedVariables> {
void SetRegisteredVariable(const AtomicString&, const CSSValue*);
const CSSValue* RegisteredVariable(const AtomicString&) const;
// This map will contain null pointers if variables are invalid due to
// cycles or referencing invalid variables without using a fallback.
// Note that this method is slow as a new map is constructed.
HashMap<AtomicString, scoped_refptr<CSSVariableData>> GetVariables() const;
// Note that not all custom property names returned here necessarily have
// valid values, due to cycles or references to invalid variables without
// using a fallback.
HashSet<AtomicString> GetCustomPropertyNames() const;
private:
StyleInheritedVariables() : root_(nullptr) {}
......
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