blob: 8f393eea6f21d644e5828125950fc2107a7bb54a [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/paint_worklet_style_property_map.h"
#include "third_party/blink/renderer/core/css/css_custom_property_declaration.h"
#include "third_party/blink/renderer/core/css/css_variable_data.h"
#include "third_party/blink/renderer/core/css/cssom/computed_style_property_map.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/properties/css_property_ref.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
namespace blink {
namespace {
class PaintWorkletStylePropertyMapIterationSource final
: public PairIterable<String, CSSStyleValueVector>::IterationSource {
public:
explicit PaintWorkletStylePropertyMapIterationSource(
HeapVector<PaintWorkletStylePropertyMap::StylePropertyMapEntry> values)
: index_(0), values_(values) {}
bool Next(ScriptState*,
String& key,
CSSStyleValueVector& value,
ExceptionState&) override {
if (index_ >= values_.size())
return false;
const PaintWorkletStylePropertyMap::StylePropertyMapEntry& pair =
values_.at(index_++);
key = pair.first;
value = pair.second;
return true;
}
void Trace(blink::Visitor* visitor) override {
visitor->Trace(values_);
PairIterable<String, CSSStyleValueVector>::IterationSource::Trace(visitor);
}
private:
wtf_size_t index_;
const HeapVector<PaintWorkletStylePropertyMap::StylePropertyMapEntry> values_;
};
} // namespace
PaintWorkletStylePropertyMap::PaintWorkletStylePropertyMap(
const Document& document,
const ComputedStyle& style,
Node* styled_node,
const Vector<CSSPropertyID>& native_properties,
const Vector<AtomicString>& custom_properties)
: StylePropertyMapReadOnly() {
DCHECK(IsMainThread());
values_.ReserveCapacityForSize(native_properties.size() +
custom_properties.size());
BuildNativeValues(style, styled_node, native_properties);
BuildCustomValues(document, style, styled_node, custom_properties);
}
void PaintWorkletStylePropertyMap::BuildNativeValues(
const ComputedStyle& style,
Node* styled_node,
const Vector<CSSPropertyID>& native_properties) {
DCHECK(IsMainThread());
for (const auto& property_id : native_properties) {
// Silently drop shorthand properties.
DCHECK_NE(property_id, CSSPropertyInvalid);
DCHECK_NE(property_id, CSSPropertyVariable);
if (CSSProperty::Get(property_id).IsShorthand())
continue;
std::unique_ptr<CrossThreadStyleValue> value =
CSSProperty::Get(property_id)
.CrossThreadStyleValueFromComputedStyle(
style, /* layout_object */ nullptr, styled_node,
/* allow_visited_style */ false);
String key = CSSProperty::Get(property_id).GetPropertyNameString();
if (!key.IsSafeToSendToAnotherThread())
key = key.IsolatedCopy();
values_.Set(key, std::move(value));
}
}
void PaintWorkletStylePropertyMap::BuildCustomValues(
const Document& document,
const ComputedStyle& style,
Node* styled_node,
const Vector<AtomicString>& custom_properties) {
DCHECK(IsMainThread());
for (const auto& property_name : custom_properties) {
CSSPropertyRef ref(property_name, document);
std::unique_ptr<CrossThreadStyleValue> value =
ref.GetProperty().CrossThreadStyleValueFromComputedStyle(
style, /* layout_object */ nullptr, styled_node,
/* allow_visited_style */ false);
// Ensure that the String can be safely passed cross threads.
String key = property_name.GetString();
if (!key.IsSafeToSendToAnotherThread())
key = key.IsolatedCopy();
values_.Set(key, std::move(value));
}
}
CSSStyleValue* PaintWorkletStylePropertyMap::get(
const ExecutionContext* execution_context,
const String& property_name,
ExceptionState& exception_state) {
CSSStyleValueVector all_values =
getAll(execution_context, property_name, exception_state);
return all_values.IsEmpty() ? nullptr : all_values[0];
}
CSSStyleValueVector PaintWorkletStylePropertyMap::getAll(
const ExecutionContext* execution_context,
const String& property_name,
ExceptionState& exception_state) {
CSSPropertyID property_id = cssPropertyID(property_name);
if (property_id == CSSPropertyInvalid) {
exception_state.ThrowTypeError("Invalid propertyName: " + property_name);
return CSSStyleValueVector();
}
DCHECK(isValidCSSPropertyID(property_id));
CSSStyleValueVector values;
auto value = values_.find(property_name);
if (value == values_.end())
return CSSStyleValueVector();
values.push_back(value->value->ToCSSStyleValue());
return values;
}
bool PaintWorkletStylePropertyMap::has(
const ExecutionContext* execution_context,
const String& property_name,
ExceptionState& exception_state) {
return !getAll(execution_context, property_name, exception_state).IsEmpty();
}
unsigned PaintWorkletStylePropertyMap::size() {
return values_.size();
}
PaintWorkletStylePropertyMap::IterationSource*
PaintWorkletStylePropertyMap::StartIteration(ScriptState* script_state,
ExceptionState& exception_state) {
// TODO(xidachen): implement this function. Note that the output should be
// sorted.
NOTREACHED();
HeapVector<PaintWorkletStylePropertyMap::StylePropertyMapEntry> result;
return MakeGarbageCollected<PaintWorkletStylePropertyMapIterationSource>(
result);
}
void PaintWorkletStylePropertyMap::Trace(blink::Visitor* visitor) {
StylePropertyMapReadOnly::Trace(visitor);
}
} // namespace blink