blob: e3aa80ce48bff5ba14a92620e41f9ba39d985652 [file] [log] [blame]
// Copyright 2016 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/properties/longhands/will_change.h"
#include "third_party/blink/renderer/core/css/css_value_list.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_token_range.h"
#include "third_party/blink/renderer/core/css/parser/css_property_parser.h"
#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
#include "third_party/blink/renderer/core/css/properties/computed_style_utils.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
namespace blink {
namespace css_longhand {
const CSSValue* WillChange::ParseSingleValue(
CSSParserTokenRange& range,
const CSSParserContext& context,
const CSSParserLocalContext&) const {
if (range.Peek().Id() == CSSValueID::kAuto)
return css_property_parser_helpers::ConsumeIdent(range);
CSSValueList* values = CSSValueList::CreateCommaSeparated();
// Every comma-separated list of identifiers is a valid will-change value,
// unless the list includes an explicitly disallowed identifier.
while (true) {
if (range.Peek().GetType() != kIdentToken)
return nullptr;
CSSPropertyID unresolved_property =
UnresolvedCSSPropertyID(range.Peek().Value());
if (unresolved_property != CSSPropertyID::kInvalid &&
unresolved_property != CSSPropertyID::kVariable) {
#if DCHECK_IS_ON()
DCHECK(CSSProperty::Get(resolveCSSPropertyID(unresolved_property))
.IsEnabled());
#endif
// Now "all" is used by both CSSValue and CSSPropertyValue.
// Need to return nullptr when currentValue is CSSPropertyID::kAll.
if (unresolved_property == CSSPropertyID::kWillChange ||
unresolved_property == CSSPropertyID::kAll)
return nullptr;
values->Append(*CSSCustomIdentValue::Create(unresolved_property));
range.ConsumeIncludingWhitespace();
} else {
switch (range.Peek().Id()) {
case CSSValueID::kNone:
case CSSValueID::kAll:
case CSSValueID::kAuto:
case CSSValueID::kDefault:
case CSSValueID::kInitial:
case CSSValueID::kInherit:
return nullptr;
case CSSValueID::kContents:
case CSSValueID::kScrollPosition:
values->Append(*css_property_parser_helpers::ConsumeIdent(range));
break;
default:
range.ConsumeIncludingWhitespace();
break;
}
}
if (range.AtEnd())
break;
if (!css_property_parser_helpers::ConsumeCommaIncludingWhitespace(range))
return nullptr;
}
return values;
}
const CSSValue* WillChange::CSSValueFromComputedStyleInternal(
const ComputedStyle& style,
const SVGComputedStyle&,
const LayoutObject*,
Node* styled_node,
bool allow_visited_style) const {
return ComputedStyleUtils::ValueForWillChange(
style.WillChangeProperties(), style.WillChangeContents(),
style.WillChangeScrollPosition());
}
void WillChange::ApplyInitial(StyleResolverState& state) const {
state.Style()->SetWillChangeContents(false);
state.Style()->SetWillChangeScrollPosition(false);
state.Style()->SetWillChangeProperties(Vector<CSSPropertyID>());
state.Style()->SetSubtreeWillChangeContents(
state.ParentStyle()->SubtreeWillChangeContents());
}
void WillChange::ApplyInherit(StyleResolverState& state) const {
state.Style()->SetWillChangeContents(
state.ParentStyle()->WillChangeContents());
state.Style()->SetWillChangeScrollPosition(
state.ParentStyle()->WillChangeScrollPosition());
state.Style()->SetWillChangeProperties(
state.ParentStyle()->WillChangeProperties());
state.Style()->SetSubtreeWillChangeContents(
state.ParentStyle()->SubtreeWillChangeContents());
}
void WillChange::ApplyValue(StyleResolverState& state,
const CSSValue& value) const {
bool will_change_contents = false;
bool will_change_scroll_position = false;
Vector<CSSPropertyID> will_change_properties;
if (auto* identifier_value = DynamicTo<CSSIdentifierValue>(value)) {
DCHECK_EQ(identifier_value->GetValueID(), CSSValueID::kAuto);
} else {
for (auto& will_change_value : To<CSSValueList>(value)) {
if (auto* ident_value =
DynamicTo<CSSCustomIdentValue>(will_change_value.Get())) {
will_change_properties.push_back(ident_value->ValueAsPropertyID());
} else if (To<CSSIdentifierValue>(*will_change_value).GetValueID() ==
CSSValueID::kContents) {
will_change_contents = true;
} else if (To<CSSIdentifierValue>(*will_change_value).GetValueID() ==
CSSValueID::kScrollPosition) {
will_change_scroll_position = true;
} else {
NOTREACHED();
}
}
}
state.Style()->SetWillChangeContents(will_change_contents);
state.Style()->SetWillChangeScrollPosition(will_change_scroll_position);
state.Style()->SetWillChangeProperties(will_change_properties);
state.Style()->SetSubtreeWillChangeContents(
will_change_contents || state.ParentStyle()->SubtreeWillChangeContents());
}
} // namespace css_longhand
} // namespace blink