diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc')
-rw-r--r-- | chromium/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc | 106 |
1 files changed, 88 insertions, 18 deletions
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc b/chromium/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc index 57172354634..48160c189ca 100644 --- a/chromium/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc +++ b/chromium/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc @@ -5,7 +5,9 @@ #include "third_party/blink/renderer/core/css/resolver/css_variable_resolver.h" #include "third_party/blink/renderer/core/css/css_custom_property_declaration.h" +#include "third_party/blink/renderer/core/css/css_invalid_variable_value.h" #include "third_party/blink/renderer/core/css/css_pending_substitution_value.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_unset_value.h" #include "third_party/blink/renderer/core/css/css_variable_data.h" #include "third_party/blink/renderer/core/css/css_variable_reference_value.h" @@ -20,7 +22,6 @@ #include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h" #include "third_party/blink/renderer/core/css/resolver/style_resolver_stats.h" #include "third_party/blink/renderer/core/css/style_engine.h" -#include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/core/dom/shadow_root.h" #include "third_party/blink/renderer/core/style/computed_style.h" @@ -85,14 +86,28 @@ scoped_refptr<CSSVariableData> ComputedVariableData( } // namespace -bool CSSVariableResolver::ResolveFallback(CSSParserTokenRange range, - const Options& options, - Result& result) { +CSSVariableResolver::Fallback CSSVariableResolver::ResolveFallback( + CSSParserTokenRange range, + const Options& options, + const PropertyRegistration* registration, + Result& result) { if (range.AtEnd()) - return false; + return Fallback::kNone; DCHECK_EQ(range.Peek().GetType(), kCommaToken); range.Consume(); - return ResolveTokenRange(range, options, result); + size_t first_fallback_token = result.tokens.size(); + if (!ResolveTokenRange(range, options, result)) + return Fallback::kFail; + if (registration) { + CSSParserTokenRange range(result.tokens); + range = range.MakeSubRange(&range.Peek(first_fallback_token), range.end()); + const CSSParserContext* context = + StrictCSSParserContext(state_.GetDocument().GetSecureContextMode()); + const bool is_animation_tainted = false; + if (!registration->Syntax().Parse(range, context, is_animation_tainted)) + return Fallback::kFail; + } + return Fallback::kSuccess; } scoped_refptr<CSSVariableData> CSSVariableResolver::ValueForCustomProperty( @@ -109,11 +124,31 @@ scoped_refptr<CSSVariableData> CSSVariableResolver::ValueForCustomProperty( CSSVariableData* variable_data = GetVariable(name, registration); - if (!variable_data) - return registration ? registration->InitialVariableData() : nullptr; + if (!variable_data) { + // For unregistered properties, not having a CSSVariableData here means + // that it either never existed, or we have resolved it earlier, but + // resolution failed. Either way, we return nullptr to signify that this is + // an invalid variable. + if (!registration) + return nullptr; + // For registered properties, it's more complicated. Here too, it can mean + // that it never existed, or that resolution failed earlier, but now we need + // to know which; in the former case we must provide the initial value, and + // in the latter case the variable is invalid. + return IsRegisteredVariableInvalid(name, *registration) + ? nullptr + : registration->InitialVariableData(); + } - scoped_refptr<CSSVariableData> resolved_data = - ResolveCustomPropertyIfNeeded(name, variable_data, options); + bool cycle_detected = false; + scoped_refptr<CSSVariableData> resolved_data = ResolveCustomPropertyIfNeeded( + name, variable_data, options, cycle_detected); + + if (!resolved_data && cycle_detected) { + if (options.absolutize) + SetInvalidVariable(name, registration); + return nullptr; + } if (resolved_data) { if (IsVariableDisallowed(*resolved_data, options, registration)) @@ -146,7 +181,8 @@ scoped_refptr<CSSVariableData> CSSVariableResolver::ValueForCustomProperty( // take inherited values instead of falling back on initial. if (registration->Inherits() && !resolved_data) { resolved_data = state_.ParentStyle()->GetVariable(name, true); - resolved_value = state_.ParentStyle()->GetRegisteredVariable(name, true); + resolved_value = + state_.ParentStyle()->GetNonInitialRegisteredVariable(name, true); } DCHECK(!!resolved_data == !!resolved_value); @@ -197,9 +233,10 @@ scoped_refptr<CSSVariableData> CSSVariableResolver::ResolveCustomProperty( bool success = ResolveTokenRange(variable_data.Tokens(), options, result); variables_seen_.erase(name); - if (!success || !cycle_start_points_.IsEmpty()) { - cycle_start_points_.erase(name); + if (!cycle_start_points_.IsEmpty()) cycle_detected = true; + if (!success || cycle_detected) { + cycle_start_points_.erase(name); return nullptr; } cycle_detected = false; @@ -219,14 +256,14 @@ scoped_refptr<CSSVariableData> CSSVariableResolver::ResolveCustomPropertyIfNeeded( AtomicString name, CSSVariableData* variable_data, - const Options& options) { + const Options& options, + bool& cycle_detected) { DCHECK(variable_data); bool resolve_urls = ShouldResolveRelativeUrls(name, *variable_data); if (!variable_data->NeedsVariableResolution() && !resolve_urls) return variable_data; - bool unused_cycle_detected; return ResolveCustomProperty(name, *variable_data, options, resolve_urls, - unused_cycle_detected); + cycle_detected); } void CSSVariableResolver::ResolveRelativeUrls( @@ -319,6 +356,25 @@ void CSSVariableResolver::SetRegisteredVariable( } } +void CSSVariableResolver::SetInvalidVariable( + const AtomicString& name, + const PropertyRegistration* registration) { + // TODO(andruud): Use RemoveVariable instead, but currently it also does + // a lookup in the registered map, which seems wasteful. + SetVariable(name, registration, nullptr); + if (registration) { + const CSSValue* value = CSSInvalidVariableValue::Create(); + SetRegisteredVariable(name, *registration, value); + } +} + +bool CSSVariableResolver::IsRegisteredVariableInvalid( + const AtomicString& name, + const PropertyRegistration& registration) { + const CSSValue* value = GetRegisteredVariable(name, registration); + return value && value->IsInvalidVariableValue(); +} + bool CSSVariableResolver::ResolveVariableReference(CSSParserTokenRange range, const Options& options, bool is_env_variable, @@ -337,6 +393,13 @@ bool CSSVariableResolver::ResolveVariableReference(CSSParserTokenRange range, non_inherited_variables_ = state_.Style()->NonInheritedVariables(); } + const PropertyRegistration* registration = nullptr; + if (registry_) { + registration = registry_->Registration(variable_name); + if (!is_env_variable) + registry_->MarkReferenced(variable_name); + } + scoped_refptr<CSSVariableData> variable_data = is_env_variable ? ValueForEnvironmentVariable(variable_name) : ValueForCustomProperty(variable_name, options); @@ -344,7 +407,8 @@ bool CSSVariableResolver::ResolveVariableReference(CSSParserTokenRange range, if (!variable_data) { // TODO(alancutter): Append the registered initial custom property value if // we are disallowing an animation tainted value. - return ResolveFallback(range, options, result); + return ResolveFallback(range, options, registration, result) == + Fallback::kSuccess; } result.tokens.AppendVector(variable_data->Tokens()); @@ -356,7 +420,13 @@ bool CSSVariableResolver::ResolveVariableReference(CSSParserTokenRange range, result.absolutized &= variable_data->IsAbsolutized(); Result trash; - ResolveFallback(range, options, trash); + Fallback fallback = ResolveFallback(range, options, registration, trash); + + // For registered properties, the fallback (if present) must be valid, even + // if it's not used. + if (registration && fallback == Fallback::kFail) + return false; + return true; } |