blob: 7141f4ef7395f29a913d1e232200e0c30dbb682e [file] [log] [blame]
/*
* (C) 1999-2003 Lars Knoll (knoll@kde.org)
* Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012, 2013 Apple Inc.
* All rights reserved.
* Copyright (C) 2011 Research In Motion Limited. All rights reserved.
* Copyright (C) 2013 Intel Corporation. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
#include "third_party/blink/renderer/core/css/css_custom_property_declaration.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.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/properties/css_property.h"
#include "third_party/blink/renderer/core/css/style_property_serializer.h"
#include "third_party/blink/renderer/core/css/style_sheet_contents.h"
#include "third_party/blink/renderer/core/style_property_shorthand.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/wtf/size_assertions.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#ifndef NDEBUG
#include <stdio.h>
#endif
namespace blink {
static AdditionalBytes
AdditionalBytesForImmutableCSSPropertyValueSetWithPropertyCount(
unsigned count) {
return AdditionalBytes(sizeof(Member<CSSValue>) * count +
sizeof(CSSPropertyValueMetadata) * count);
}
ImmutableCSSPropertyValueSet* ImmutableCSSPropertyValueSet::Create(
const CSSPropertyValue* properties,
unsigned count,
CSSParserMode css_parser_mode) {
DCHECK_LE(count, static_cast<unsigned>(kMaxArraySize));
return MakeGarbageCollected<ImmutableCSSPropertyValueSet>(
AdditionalBytesForImmutableCSSPropertyValueSetWithPropertyCount(count),
properties, count, css_parser_mode);
}
ImmutableCSSPropertyValueSet* CSSPropertyValueSet::ImmutableCopyIfNeeded()
const {
auto* immutable_property_set = DynamicTo<ImmutableCSSPropertyValueSet>(
const_cast<CSSPropertyValueSet*>(this));
if (immutable_property_set)
return immutable_property_set;
const auto* mutable_this = To<MutableCSSPropertyValueSet>(this);
return ImmutableCSSPropertyValueSet::Create(
mutable_this->property_vector_.data(),
mutable_this->property_vector_.size(), CssParserMode());
}
MutableCSSPropertyValueSet::MutableCSSPropertyValueSet(
CSSParserMode css_parser_mode)
: CSSPropertyValueSet(css_parser_mode) {}
MutableCSSPropertyValueSet::MutableCSSPropertyValueSet(
const CSSPropertyValue* properties,
unsigned length)
: CSSPropertyValueSet(kHTMLStandardMode) {
property_vector_.ReserveInitialCapacity(length);
for (unsigned i = 0; i < length; ++i) {
property_vector_.UncheckedAppend(properties[i]);
if (!may_have_logical_properties_) {
const CSSProperty& prop = CSSProperty::Get(properties[i].Id());
may_have_logical_properties_ =
prop.IsInLogicalPropertyGroup() && prop.IsSurrogate();
}
}
}
ImmutableCSSPropertyValueSet::ImmutableCSSPropertyValueSet(
const CSSPropertyValue* properties,
unsigned length,
CSSParserMode css_parser_mode)
: CSSPropertyValueSet(css_parser_mode, length) {
CSSPropertyValueMetadata* metadata_array =
const_cast<CSSPropertyValueMetadata*>(this->MetadataArray());
Member<const CSSValue>* value_array =
const_cast<Member<const CSSValue>*>(this->ValueArray());
for (unsigned i = 0; i < array_size_; ++i) {
metadata_array[i] = properties[i].Metadata();
value_array[i] = properties[i].Value();
}
}
// Convert property into an uint16_t for comparison with metadata's property id
// to avoid the compiler converting it to an int multiple times in a loop.
static uint16_t GetConvertedCSSPropertyID(CSSPropertyID property_id) {
return static_cast<uint16_t>(property_id);
}
static uint16_t GetConvertedCSSPropertyID(const AtomicString&) {
return static_cast<uint16_t>(CSSPropertyID::kVariable);
}
static uint16_t GetConvertedCSSPropertyID(AtRuleDescriptorID descriptor_id) {
return static_cast<uint16_t>(
AtRuleDescriptorIDAsCSSPropertyID(descriptor_id));
}
static bool IsPropertyMatch(const CSSPropertyValueMetadata& metadata,
const CSSValue&,
uint16_t id,
CSSPropertyID property_id) {
DCHECK_EQ(id, static_cast<uint16_t>(property_id));
bool result = static_cast<uint16_t>(metadata.PropertyID()) == id;
// Only enabled properties except kInternalFontSizeDelta should be part of the
// style.
// TODO(hjkim3323@gmail.com): Remove kInternalFontSizeDelta bypassing hack
#if DCHECK_IS_ON()
DCHECK(!result || property_id == CSSPropertyID::kInternalFontSizeDelta ||
CSSProperty::Get(ResolveCSSPropertyID(property_id)).IsWebExposed());
#endif
return result;
}
static bool IsPropertyMatch(const CSSPropertyValueMetadata& metadata,
const CSSValue& value,
uint16_t id,
const AtomicString& custom_property_name) {
DCHECK_EQ(id, static_cast<uint16_t>(CSSPropertyID::kVariable));
return static_cast<uint16_t>(metadata.PropertyID()) == id &&
To<CSSCustomPropertyDeclaration>(value).GetName() ==
custom_property_name;
}
static bool IsPropertyMatch(const CSSPropertyValueMetadata& metadata,
const CSSValue& css_value,
uint16_t id,
AtRuleDescriptorID descriptor_id) {
return IsPropertyMatch(metadata, css_value, id,
AtRuleDescriptorIDAsCSSPropertyID(descriptor_id));
}
template <typename T>
int ImmutableCSSPropertyValueSet::FindPropertyIndex(T property) const {
uint16_t id = GetConvertedCSSPropertyID(property);
for (int n = array_size_ - 1; n >= 0; --n) {
if (IsPropertyMatch(MetadataArray()[n], *ValueArray()[n], id, property))
return n;
}
return -1;
}
template CORE_EXPORT int ImmutableCSSPropertyValueSet::FindPropertyIndex(
CSSPropertyID) const;
template CORE_EXPORT int ImmutableCSSPropertyValueSet::FindPropertyIndex(
AtomicString) const;
template CORE_EXPORT int ImmutableCSSPropertyValueSet::FindPropertyIndex(
AtRuleDescriptorID) const;
void ImmutableCSSPropertyValueSet::TraceAfterDispatch(
blink::Visitor* visitor) const {
const Member<const CSSValue>* values = ValueArray();
for (unsigned i = 0; i < array_size_; i++)
visitor->Trace(values[i]);
CSSPropertyValueSet::TraceAfterDispatch(visitor);
}
MutableCSSPropertyValueSet::MutableCSSPropertyValueSet(
const CSSPropertyValueSet& other)
: CSSPropertyValueSet(other.CssParserMode()) {
if (auto* other_mutable_property_set =
DynamicTo<MutableCSSPropertyValueSet>(other)) {
property_vector_ = other_mutable_property_set->property_vector_;
may_have_logical_properties_ =
other_mutable_property_set->may_have_logical_properties_;
} else {
property_vector_.ReserveInitialCapacity(other.PropertyCount());
for (unsigned i = 0; i < other.PropertyCount(); ++i) {
PropertyReference property = other.PropertyAt(i);
property_vector_.UncheckedAppend(
CSSPropertyValue(property.PropertyMetadata(), property.Value()));
if (!may_have_logical_properties_) {
const CSSProperty& prop = CSSProperty::Get(property.Id());
may_have_logical_properties_ =
prop.IsInLogicalPropertyGroup() && prop.IsSurrogate();
}
}
}
}
static String SerializeShorthand(const CSSPropertyValueSet& property_set,
CSSPropertyID property_id) {
StylePropertyShorthand shorthand = shorthandForProperty(property_id);
if (!shorthand.length())
return String();
return StylePropertySerializer(property_set).SerializeShorthand(property_id);
}
static String SerializeShorthand(const CSSPropertyValueSet&,
const AtomicString& custom_property_name) {
// Custom properties are never shorthands.
return String();
}
static String SerializeShorthand(const CSSPropertyValueSet& property_set,
AtRuleDescriptorID atrule_id) {
// Descriptor shorthands aren't handled yet.
return String();
}
template <typename T>
String CSSPropertyValueSet::GetPropertyValue(T property) const {
String shorthand_serialization = SerializeShorthand(*this, property);
if (!shorthand_serialization.IsNull())
return shorthand_serialization;
const CSSValue* value = GetPropertyCSSValue(property);
if (value)
return value->CssText();
return g_empty_string;
}
template CORE_EXPORT String
CSSPropertyValueSet::GetPropertyValue<CSSPropertyID>(CSSPropertyID) const;
template CORE_EXPORT String
CSSPropertyValueSet::GetPropertyValue<AtRuleDescriptorID>(
AtRuleDescriptorID) const;
template CORE_EXPORT String
CSSPropertyValueSet::GetPropertyValue<AtomicString>(AtomicString) const;
template <typename T>
const CSSValue* CSSPropertyValueSet::GetPropertyCSSValue(T property) const {
int found_property_index = FindPropertyIndex(property);
if (found_property_index == -1)
return nullptr;
return &PropertyAt(found_property_index).Value();
}
template CORE_EXPORT const CSSValue* CSSPropertyValueSet::GetPropertyCSSValue<
CSSPropertyID>(CSSPropertyID) const;
template CORE_EXPORT const CSSValue* CSSPropertyValueSet::GetPropertyCSSValue<
AtRuleDescriptorID>(AtRuleDescriptorID) const;
template CORE_EXPORT const CSSValue*
CSSPropertyValueSet::GetPropertyCSSValue<AtomicString>(AtomicString) const;
void CSSPropertyValueSet::Trace(Visitor* visitor) const {
if (is_mutable_)
To<MutableCSSPropertyValueSet>(this)->TraceAfterDispatch(visitor);
else
To<ImmutableCSSPropertyValueSet>(this)->TraceAfterDispatch(visitor);
}
void CSSPropertyValueSet::FinalizeGarbageCollectedObject() {
if (is_mutable_)
To<MutableCSSPropertyValueSet>(this)->~MutableCSSPropertyValueSet();
else
To<ImmutableCSSPropertyValueSet>(this)->~ImmutableCSSPropertyValueSet();
}
bool MutableCSSPropertyValueSet::RemoveShorthandProperty(
CSSPropertyID property_id) {
StylePropertyShorthand shorthand = shorthandForProperty(property_id);
if (!shorthand.length())
return false;
return RemovePropertiesInSet(shorthand.properties(), shorthand.length());
}
bool MutableCSSPropertyValueSet::RemovePropertyAtIndex(int property_index,
String* return_text) {
if (property_index == -1) {
if (return_text)
*return_text = "";
return false;
}
if (return_text)
*return_text = PropertyAt(property_index).Value().CssText();
// A more efficient removal strategy would involve marking entries as empty
// and sweeping them when the vector grows too big.
property_vector_.EraseAt(property_index);
return true;
}
template <typename T>
bool MutableCSSPropertyValueSet::RemoveProperty(T property,
String* return_text) {
if (RemoveShorthandProperty(property)) {
// FIXME: Return an equivalent shorthand when possible.
if (return_text)
*return_text = "";
return true;
}
int found_property_index = FindPropertyIndex(property);
return RemovePropertyAtIndex(found_property_index, return_text);
}
template CORE_EXPORT bool MutableCSSPropertyValueSet::RemoveProperty(
CSSPropertyID,
String*);
template CORE_EXPORT bool MutableCSSPropertyValueSet::RemoveProperty(
AtomicString,
String*);
template <typename T>
bool CSSPropertyValueSet::PropertyIsImportant(T property) const {
int found_property_index = FindPropertyIndex(property);
if (found_property_index != -1)
return PropertyAt(found_property_index).IsImportant();
return ShorthandIsImportant(property);
}
template bool CSSPropertyValueSet::PropertyIsImportant<CSSPropertyID>(
CSSPropertyID) const;
template bool CSSPropertyValueSet::PropertyIsImportant<AtomicString>(
AtomicString) const;
bool CSSPropertyValueSet::ShorthandIsImportant(
CSSPropertyID property_id) const {
StylePropertyShorthand shorthand = shorthandForProperty(property_id);
if (!shorthand.length())
return false;
for (unsigned i = 0; i < shorthand.length(); ++i) {
if (!PropertyIsImportant(shorthand.properties()[i]->PropertyID()))
return false;
}
return true;
}
bool CSSPropertyValueSet::ShorthandIsImportant(
AtomicString custom_property_name) const {
// Custom properties are never shorthands.
return false;
}
CSSPropertyID CSSPropertyValueSet::GetPropertyShorthand(
CSSPropertyID property_id) const {
int found_property_index = FindPropertyIndex(property_id);
if (found_property_index == -1)
return CSSPropertyID::kInvalid;
return PropertyAt(found_property_index).ShorthandID();
}
bool CSSPropertyValueSet::IsPropertyImplicit(CSSPropertyID property_id) const {
int found_property_index = FindPropertyIndex(property_id);
if (found_property_index == -1)
return false;
return PropertyAt(found_property_index).IsImplicit();
}
MutableCSSPropertyValueSet::SetResult MutableCSSPropertyValueSet::SetProperty(
CSSPropertyID unresolved_property,
const String& value,
bool important,
SecureContextMode secure_context_mode,
StyleSheetContents* context_style_sheet) {
DCHECK_GE(unresolved_property, kFirstCSSProperty);
// Setting the value to an empty string just removes the property in both IE
// and Gecko. Setting it to null seems to produce less consistent results, but
// we treat it just the same.
if (value.IsEmpty()) {
bool did_parse = true;
bool did_change = RemoveProperty(ResolveCSSPropertyID(unresolved_property));
return SetResult{did_parse, did_change};
}
// When replacing an existing property value, this moves the property to the
// end of the list. Firefox preserves the position, and MSIE moves the
// property to the beginning.
return CSSParser::ParseValue(this, unresolved_property, value, important,
secure_context_mode, context_style_sheet);
}
MutableCSSPropertyValueSet::SetResult MutableCSSPropertyValueSet::SetProperty(
const AtomicString& custom_property_name,
const String& value,
bool important,
SecureContextMode secure_context_mode,
StyleSheetContents* context_style_sheet,
bool is_animation_tainted) {
if (value.IsEmpty()) {
bool did_parse = true;
bool did_change = RemoveProperty(custom_property_name);
return MutableCSSPropertyValueSet::SetResult{did_parse, did_change};
}
return CSSParser::ParseValueForCustomProperty(
this, custom_property_name, value, important, secure_context_mode,
context_style_sheet, is_animation_tainted);
}
void MutableCSSPropertyValueSet::SetProperty(CSSPropertyID property_id,
const CSSValue& value,
bool important) {
StylePropertyShorthand shorthand = shorthandForProperty(property_id);
if (!shorthand.length()) {
// TODO(crbug.com/1112291): Don't use this function for custom properties.
CSSPropertyName name =
(property_id == CSSPropertyID::kVariable)
? CSSPropertyName(To<CSSCustomPropertyDeclaration>(value).GetName())
: CSSPropertyName(property_id);
SetProperty(CSSPropertyValue(name, value, important));
return;
}
RemovePropertiesInSet(shorthand.properties(), shorthand.length());
for (unsigned i = 0; i < shorthand.length(); ++i) {
CSSPropertyName name(shorthand.properties()[i]->PropertyID());
property_vector_.push_back(CSSPropertyValue(name, value, important));
}
}
bool MutableCSSPropertyValueSet::SetProperty(const CSSPropertyValue& property,
CSSPropertyValue* slot) {
CSSPropertyValue* to_replace =
slot ? slot : FindCSSPropertyWithName(property.Name());
if (to_replace) {
if (may_have_logical_properties_) {
const CSSProperty& prop = CSSProperty::Get(property.Id());
if (prop.IsInLogicalPropertyGroup()) {
DCHECK(property_vector_.Contains(*to_replace));
int to_replace_index = to_replace - property_vector_.begin();
for (int n = property_vector_.size() - 1; n > to_replace_index; --n) {
if (prop.IsInSameLogicalPropertyGroupWithDifferentMappingLogic(
PropertyAt(n).Id())) {
RemovePropertyAtIndex(to_replace_index, nullptr);
to_replace = nullptr;
break;
}
}
}
}
if (to_replace) {
if (*to_replace == property)
return false;
*to_replace = property;
return true;
}
} else if (!may_have_logical_properties_) {
const CSSProperty& prop = CSSProperty::Get(property.Id());
may_have_logical_properties_ =
prop.IsInLogicalPropertyGroup() && prop.IsSurrogate();
}
property_vector_.push_back(property);
return true;
}
bool MutableCSSPropertyValueSet::SetProperty(CSSPropertyID property_id,
CSSValueID identifier,
bool important) {
CSSPropertyName name(property_id);
SetProperty(CSSPropertyValue(name, *CSSIdentifierValue::Create(identifier),
important));
return true;
}
void MutableCSSPropertyValueSet::ParseDeclarationList(
const String& style_declaration,
SecureContextMode secure_context_mode,
StyleSheetContents* context_style_sheet) {
property_vector_.clear();
CSSParserContext* context;
if (context_style_sheet) {
context = MakeGarbageCollected<CSSParserContext>(
context_style_sheet->ParserContext(), context_style_sheet);
context->SetMode(CssParserMode());
} else {
context = MakeGarbageCollected<CSSParserContext>(CssParserMode(),
secure_context_mode);
}
CSSParser::ParseDeclarationList(context, this, style_declaration);
}
bool MutableCSSPropertyValueSet::AddParsedProperties(
const HeapVector<CSSPropertyValue, 256>& properties) {
bool changed = false;
property_vector_.ReserveCapacity(property_vector_.size() + properties.size());
for (unsigned i = 0; i < properties.size(); ++i)
changed |= SetProperty(properties[i]);
return changed;
}
bool MutableCSSPropertyValueSet::AddRespectingCascade(
const CSSPropertyValue& property) {
// Only add properties that have no !important counterpart present
if (!PropertyIsImportant(property.Id()) || property.IsImportant())
return SetProperty(property);
return false;
}
String CSSPropertyValueSet::AsText() const {
return StylePropertySerializer(*this).AsText();
}
void MutableCSSPropertyValueSet::MergeAndOverrideOnConflict(
const CSSPropertyValueSet* other) {
unsigned size = other->PropertyCount();
for (unsigned n = 0; n < size; ++n) {
PropertyReference to_merge = other->PropertyAt(n);
CSSPropertyValue* old = FindCSSPropertyWithName(to_merge.Name());
if (old) {
SetProperty(
CSSPropertyValue(to_merge.PropertyMetadata(), to_merge.Value()), old);
} else {
property_vector_.push_back(
CSSPropertyValue(to_merge.PropertyMetadata(), to_merge.Value()));
}
}
}
bool CSSPropertyValueSet::HasFailedOrCanceledSubresources() const {
unsigned size = PropertyCount();
for (unsigned i = 0; i < size; ++i) {
if (PropertyAt(i).Value().HasFailedOrCanceledSubresources())
return true;
}
return false;
}
void MutableCSSPropertyValueSet::Clear() {
property_vector_.clear();
may_have_logical_properties_ = false;
}
inline bool ContainsId(const CSSProperty* const set[],
unsigned length,
CSSPropertyID id) {
for (unsigned i = 0; i < length; ++i) {
if (set[i]->IDEquals(id))
return true;
}
return false;
}
bool MutableCSSPropertyValueSet::RemovePropertiesInSet(
const CSSProperty* const set[],
unsigned length) {
if (property_vector_.IsEmpty())
return false;
CSSPropertyValue* properties = property_vector_.data();
unsigned old_size = property_vector_.size();
unsigned new_index = 0;
for (unsigned old_index = 0; old_index < old_size; ++old_index) {
const CSSPropertyValue& property = properties[old_index];
if (ContainsId(set, length, property.Id()))
continue;
// Modify property_vector_ in-place since this method is
// performance-sensitive.
properties[new_index++] = properties[old_index];
}
if (new_index != old_size) {
property_vector_.Shrink(new_index);
return true;
}
return false;
}
CSSPropertyValue* MutableCSSPropertyValueSet::FindCSSPropertyWithName(
const CSSPropertyName& name) {
int found_property_index = name.IsCustomProperty()
? FindPropertyIndex(name.ToAtomicString())
: FindPropertyIndex(name.Id());
if (found_property_index == -1)
return nullptr;
return &property_vector_.at(found_property_index);
}
bool CSSPropertyValueSet::PropertyMatches(
CSSPropertyID property_id,
const CSSValue& property_value) const {
int found_property_index = FindPropertyIndex(property_id);
if (found_property_index == -1)
return false;
return PropertyAt(found_property_index).Value() == property_value;
}
void MutableCSSPropertyValueSet::RemoveEquivalentProperties(
const CSSPropertyValueSet* style) {
Vector<CSSPropertyID> properties_to_remove;
unsigned size = property_vector_.size();
for (unsigned i = 0; i < size; ++i) {
PropertyReference property = PropertyAt(i);
if (style->PropertyMatches(property.Id(), property.Value()))
properties_to_remove.push_back(property.Id());
}
// FIXME: This should use mass removal.
for (unsigned i = 0; i < properties_to_remove.size(); ++i)
RemoveProperty(properties_to_remove[i]);
}
void MutableCSSPropertyValueSet::RemoveEquivalentProperties(
const CSSStyleDeclaration* style) {
Vector<CSSPropertyID> properties_to_remove;
unsigned size = property_vector_.size();
for (unsigned i = 0; i < size; ++i) {
PropertyReference property = PropertyAt(i);
if (style->CssPropertyMatches(property.Id(), property.Value()))
properties_to_remove.push_back(property.Id());
}
// FIXME: This should use mass removal.
for (unsigned i = 0; i < properties_to_remove.size(); ++i)
RemoveProperty(properties_to_remove[i]);
}
MutableCSSPropertyValueSet* CSSPropertyValueSet::MutableCopy() const {
return MakeGarbageCollected<MutableCSSPropertyValueSet>(*this);
}
MutableCSSPropertyValueSet* CSSPropertyValueSet::CopyPropertiesInSet(
const Vector<const CSSProperty*>& properties) const {
HeapVector<CSSPropertyValue, 256> list;
list.ReserveInitialCapacity(properties.size());
for (unsigned i = 0; i < properties.size(); ++i) {
CSSPropertyName name(properties[i]->PropertyID());
const CSSValue* value = GetPropertyCSSValue(name.Id());
if (value)
list.push_back(CSSPropertyValue(name, *value, false));
}
return MakeGarbageCollected<MutableCSSPropertyValueSet>(list.data(),
list.size());
}
CSSStyleDeclaration* MutableCSSPropertyValueSet::EnsureCSSStyleDeclaration(
ExecutionContext* execution_context) {
// FIXME: get rid of this weirdness of a CSSStyleDeclaration inside of a
// style property set.
if (cssom_wrapper_) {
DCHECK(
!static_cast<CSSStyleDeclaration*>(cssom_wrapper_.Get())->parentRule());
DCHECK(!cssom_wrapper_->ParentElement());
return cssom_wrapper_.Get();
}
cssom_wrapper_ = MakeGarbageCollected<PropertySetCSSStyleDeclaration>(
execution_context, *this);
return cssom_wrapper_.Get();
}
template <typename T>
int MutableCSSPropertyValueSet::FindPropertyIndex(T property) const {
const CSSPropertyValue* begin = property_vector_.data();
const CSSPropertyValue* end = begin + property_vector_.size();
uint16_t id = GetConvertedCSSPropertyID(property);
const CSSPropertyValue* it = std::find_if(
begin, end, [property, id](const CSSPropertyValue& css_property) -> bool {
return IsPropertyMatch(css_property.Metadata(), *css_property.Value(),
id, property);
});
return (it == end) ? -1 : static_cast<int>(it - begin);
}
template CORE_EXPORT int MutableCSSPropertyValueSet::FindPropertyIndex(
CSSPropertyID) const;
template CORE_EXPORT int MutableCSSPropertyValueSet::FindPropertyIndex(
AtomicString) const;
void MutableCSSPropertyValueSet::TraceAfterDispatch(
blink::Visitor* visitor) const {
visitor->Trace(cssom_wrapper_);
visitor->Trace(property_vector_);
CSSPropertyValueSet::TraceAfterDispatch(visitor);
}
unsigned CSSPropertyValueSet::AverageSizeInBytes() {
// Please update this if the storage scheme changes so that this longer
// reflects the actual size.
return sizeof(ImmutableCSSPropertyValueSet) +
AdditionalBytesForImmutableCSSPropertyValueSetWithPropertyCount(4)
.value;
}
// See the function above if you need to update this.
struct SameSizeAsCSSPropertyValueSet final
: public GarbageCollected<SameSizeAsCSSPropertyValueSet> {
uint32_t bitfield;
};
ASSERT_SIZE(CSSPropertyValueSet, SameSizeAsCSSPropertyValueSet);
#ifndef NDEBUG
void CSSPropertyValueSet::ShowStyle() {
fprintf(stderr, "%s\n", AsText().Ascii().c_str());
}
#endif
void CSSLazyPropertyParser::Trace(Visitor* visitor) const {}
} // namespace blink