blob: 79f7bd3d66752bf378cb33e698c5410dbd6e9a3b [file] [log] [blame]
// Copyright 2018 the chromium authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.h"
#include "third_party/blink/renderer/core/css/css_custom_property_declaration.h"
#include "third_party/blink/renderer/core/css/css_property_name.h"
#include "third_party/blink/renderer/core/css/css_property_names.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_style_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_unparsed_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_unsupported_style_value.h"
#include "third_party/blink/renderer/core/css/cssom/style_value_factory.h"
#include "third_party/blink/renderer/core/css/properties/css_property.h"
#include "third_party/blink/renderer/core/css/property_registration.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"
namespace blink {
namespace {
class StylePropertyMapIterationSource final
: public PairIterable<String, CSSStyleValueVector>::IterationSource {
public:
explicit StylePropertyMapIterationSource(
HeapVector<StylePropertyMapReadOnlyMainThread::StylePropertyMapEntry>
values)
: index_(0), values_(values) {}
bool Next(ScriptState*,
String& key,
CSSStyleValueVector& value,
ExceptionState&) override {
if (index_ >= values_.size())
return false;
const StylePropertyMapReadOnlyMainThread::StylePropertyMapEntry& pair =
values_.at(index_++);
key = pair.first;
value = pair.second;
return true;
}
void Trace(Visitor* visitor) const override {
visitor->Trace(values_);
PairIterable<String, CSSStyleValueVector>::IterationSource::Trace(visitor);
}
private:
wtf_size_t index_;
const HeapVector<StylePropertyMapReadOnlyMainThread::StylePropertyMapEntry>
values_;
};
} // namespace
CSSStyleValue* StylePropertyMapReadOnlyMainThread::get(
const ExecutionContext* execution_context,
const String& property_name,
ExceptionState& exception_state) const {
base::Optional<CSSPropertyName> name =
CSSPropertyName::From(execution_context, property_name);
if (!name) {
exception_state.ThrowTypeError("Invalid propertyName: " + property_name);
return nullptr;
}
const CSSProperty& property = CSSProperty::Get(name->Id());
if (property.IsShorthand())
return GetShorthandProperty(property);
const CSSValue* value = (name->IsCustomProperty())
? GetCustomProperty(name->ToAtomicString())
: GetProperty(name->Id());
if (!value)
return nullptr;
// Custom properties count as repeated whenever we have a CSSValueList.
if (property.IsRepeated() ||
(name->IsCustomProperty() && value->IsValueList())) {
CSSStyleValueVector values =
StyleValueFactory::CssValueToStyleValueVector(*name, *value);
return values.IsEmpty() ? nullptr : values[0];
}
return StyleValueFactory::CssValueToStyleValue(*name, *value);
}
CSSStyleValueVector StylePropertyMapReadOnlyMainThread::getAll(
const ExecutionContext* execution_context,
const String& property_name,
ExceptionState& exception_state) const {
base::Optional<CSSPropertyName> name =
CSSPropertyName::From(execution_context, property_name);
if (!name) {
exception_state.ThrowTypeError("Invalid propertyName: " + property_name);
return CSSStyleValueVector();
}
const CSSProperty& property = CSSProperty::Get(name->Id());
if (property.IsShorthand()) {
CSSStyleValueVector values;
if (CSSStyleValue* value = GetShorthandProperty(property))
values.push_back(value);
return values;
}
const CSSValue* value = (name->IsCustomProperty())
? GetCustomProperty(name->ToAtomicString())
: GetProperty(name->Id());
if (!value)
return CSSStyleValueVector();
return StyleValueFactory::CssValueToStyleValueVector(*name, *value);
}
bool StylePropertyMapReadOnlyMainThread::has(
const ExecutionContext* execution_context,
const String& property_name,
ExceptionState& exception_state) const {
return !getAll(execution_context, property_name, exception_state).IsEmpty();
}
StylePropertyMapReadOnlyMainThread::IterationSource*
StylePropertyMapReadOnlyMainThread::StartIteration(ScriptState* script_state,
ExceptionState&) {
HeapVector<StylePropertyMapReadOnlyMainThread::StylePropertyMapEntry> result;
ForEachProperty([&result](const CSSPropertyName& name,
const CSSValue& value) {
auto values = StyleValueFactory::CssValueToStyleValueVector(name, value);
result.emplace_back(name.ToAtomicString(), std::move(values));
});
return MakeGarbageCollected<StylePropertyMapIterationSource>(result);
}
CSSStyleValue* StylePropertyMapReadOnlyMainThread::GetShorthandProperty(
const CSSProperty& property) const {
DCHECK(property.IsShorthand());
const auto serialization = SerializationForShorthand(property);
if (serialization.IsEmpty())
return nullptr;
return MakeGarbageCollected<CSSUnsupportedStyleValue>(
CSSPropertyName(property.PropertyID()), serialization);
}
} // namespace blink