blob: 7c3f8808bbafaa07e17d3e064374ca7b45037977 [file] [log] [blame]
// Copyright 2020 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.
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_CASCADE_RESOLVER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_CASCADE_RESOLVER_H_
#include "base/auto_reset.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/css_property_name.h"
#include "third_party/blink/renderer/core/css/properties/css_property.h"
#include "third_party/blink/renderer/core/css/resolver/cascade_filter.h"
#include "third_party/blink/renderer/core/css/resolver/cascade_origin.h"
#include "third_party/blink/renderer/core/css/rule_set.h"
namespace blink {
class CascadePriority;
class CSSProperty;
class CSSVariableData;
class CSSProperty;
namespace cssvalue {
class CSSPendingSubstitutionValue;
} // namespace cssvalue
// CascadeResolver is an object passed on the stack during Apply. Its most
// important job is to detect cycles during Apply (in general, keep track of
// which properties we're currently applying).
class CORE_EXPORT CascadeResolver {
STACK_ALLOCATED();
public:
// TODO(crbug.com/985047): Probably use a HashMap for this.
using PropertyStack = Vector<const CSSProperty*, 8>;
// A 'locked' property is a property we are in the process of applying.
// In other words, once a property is locked, locking it again would form
// a cycle, and is therefore an error.
bool IsLocked(const CSSProperty&) const;
// Returns the property we're currently applying.
const CSSProperty* CurrentProperty() const {
return stack_.size() ? stack_.back() : nullptr;
}
// We do not allow substitution of animation-tainted values into
// an animation-affecting property.
//
// https://drafts.csswg.org/css-variables/#animation-tainted
bool AllowSubstitution(CSSVariableData*) const;
// Sets the generation of the priority to zero, which has the effect of
// marking it as unapplied. (I.e. this can be used to force re-application of
// a declaration).
void MarkUnapplied(CascadePriority*) const;
// Sets the generation of the priority to the current generation,
// which has the effect of marking it as already applied. (I.e. this can be
// used to skip application of a declaration).
void MarkApplied(CascadePriority*) const;
// If the incoming origin is kAuthor, collect flags from 'property'.
// AuthorFlags() can then later be used to see which flags have been observed.
void CollectAuthorFlags(const CSSProperty& property, CascadeOrigin origin) {
author_flags_ |=
(origin == CascadeOrigin::kAuthor ? property.GetFlags() : 0);
}
CSSProperty::Flags AuthorFlags() const { return author_flags_; }
// Automatically locks and unlocks the given property. (See
// CascadeResolver::IsLocked).
class CORE_EXPORT AutoLock {
STACK_ALLOCATED();
public:
AutoLock(const CSSProperty&, CascadeResolver&);
~AutoLock();
private:
CascadeResolver& resolver_;
};
private:
friend class AutoLock;
friend class StyleCascade;
friend class TestCascadeResolver;
CascadeResolver(CascadeFilter filter, uint8_t generation)
: filter_(filter), generation_(generation) {}
// If the given property is already being applied, returns true.
// The return value is the same value you would get from InCycle(), and
// is just returned for convenience.
//
// When a cycle has been detected, the CascadeResolver will *persist the cycle
// state* (i.e. InCycle() will continue to return true) until we reach
// the start of the cycle.
//
// The cycle state is cleared by ~AutoLock, once we have moved far enough
// up the stack.
bool DetectCycle(const CSSProperty&);
// Returns true whenever the CascadeResolver is in a cycle state.
// This DOES NOT detect cycles; the caller must call DetectCycle first.
bool InCycle() const;
// Returns the index of the given property (compared using the property's
// CSSPropertyName), or kNotFound if the property (name) is not present in
// stack_.
wtf_size_t Find(const CSSProperty&) const;
PropertyStack stack_;
wtf_size_t cycle_depth_ = kNotFound;
CascadeFilter filter_;
const uint8_t generation_ = 0;
CSSProperty::Flags author_flags_ = 0;
// A very simple cache for CSSPendingSubstitutionValues. We cache only the
// most recently parsed CSSPendingSubstitutionValue, such that consecutive
// calls to ResolvePendingSubstitution with the same value don't need to
// do the same parsing job all over again.
struct {
STACK_ALLOCATED();
public:
const cssvalue::CSSPendingSubstitutionValue* value = nullptr;
HeapVector<CSSPropertyValue, 256> parsed_properties;
} shorthand_cache_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_CASCADE_RESOLVER_H_