Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(410)

Side by Side Diff: third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp

Issue 1192983003: CSS Custom Properties (Variables) (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Remove reftest.list :( Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "config.h"
6 #include "core/css/resolver/CSSVariableResolver.h"
7
8 #include "core/CSSPropertyNames.h"
9 #include "core/CSSValueKeywords.h"
10 #include "core/StyleBuilderFunctions.h"
11 #include "core/css/CSSVariableData.h"
12 #include "core/css/CSSVariableReferenceValue.h"
13 #include "core/css/parser/CSSParserToken.h"
14 #include "core/css/parser/CSSParserTokenRange.h"
15 #include "core/css/parser/CSSParserValues.h"
16 #include "core/css/parser/CSSPropertyParser.h"
17 #include "core/css/resolver/StyleBuilder.h"
18 #include "core/css/resolver/StyleResolverState.h"
19 #include "core/style/StyleVariableData.h"
20 #include "wtf/Vector.h"
21
22 namespace blink {
23
24 // TODO(leviw): This should take a CSSParserTokenRange
25 static void findEndOfVariableReference(const Vector<CSSParserToken>& resolvedTok ens, unsigned startOffset, unsigned& end, unsigned& commaLocation)
Timothy Loh 2015/10/28 05:12:41 Maybe startIndex, endIndex, commaIndex (as well as
leviw_travelin_and_unemployed 2015/10/30 21:41:16 Done.
26 {
27 end = 0;
28 commaLocation = 0;
29 unsigned bracketCount = 0;
Timothy Loh 2015/10/28 05:12:41 imo, the logic below would be slightly clearer if
leviw_travelin_and_unemployed 2015/10/30 21:41:16 Done.
30 for (unsigned i = startOffset; i < resolvedTokens.size(); ++i) {
31 CSSParserTokenType type = resolvedTokens[i].type();
32
33 if (type == CommaToken && !commaLocation) {
34 commaLocation = i;
35 } else if (type == LeftParenthesisToken || type == FunctionToken) {
36 bracketCount++;
37 } else if (type == RightParenthesisToken) {
38 if (bracketCount) {
39 bracketCount--;
40 } else {
41 end = i;
42 break;
43 }
44 }
45 }
46 if (!end)
47 end = resolvedTokens.size() - 1;
48 }
49
50 unsigned CSSVariableResolver::resolveVariableTokensRecursive(Vector<CSSParserTok en>& resolvedTokens, unsigned startOffset)
51 {
52 ASSERT(startOffset);
53
54 unsigned commaLocation, end;
Timothy Loh 2015/10/28 05:12:41 I think Blink style is to have multiple variable d
leviw_travelin_and_unemployed 2015/10/30 21:41:16 Done.
55
56 // Find the variable location
57 unsigned variableLocation = 0;
Timothy Loh 2015/10/28 05:12:41 How about (we definitely have an ident, right?):
leviw_travelin_and_unemployed 2015/10/30 21:41:16 Done.
58 for (unsigned i = startOffset; i < resolvedTokens.size(); ++i) {
59 if (resolvedTokens[i].type() == IdentToken) {
60 variableLocation = i;
61 break;
62 }
63 }
64
65 // Find default value and match braces
66 findEndOfVariableReference(resolvedTokens, variableLocation + 1, end, commaL ocation);
67
68 unsigned length = end - startOffset + 2;
Timothy Loh 2015/10/28 05:12:42 All the +1s and -1s are a bit hard to follow. This
leviw_travelin_and_unemployed 2015/10/30 21:41:16 Addressed.
69 unsigned varFunctionPosition = startOffset - 1;
70
71 AtomicString variableName = resolvedTokens[variableLocation].value();
72
73 if (m_variablesSeen.contains(variableName)) {
74 m_cycleDetected = true;
75 resolvedTokens.clear();
76 return 0;
77 }
78
79 CSSVariableData* variableData = m_styleVariableData ? m_styleVariableData->g etVariable(variableName) : nullptr;
80 if (variableData) {
81 Vector<CSSParserToken> tokens(variableData->tokens());
82 if (variableData->needsVariableResolution()) {
83 m_variablesSeen.add(variableName);
84 resolveVariableReferencesFromTokens(tokens);
85 m_variablesSeen.remove(variableName);
86
87 m_styleVariableData->setVariable(variableName, CSSVariableData::crea teResolved(tokens));
88 }
89 if (tokens.size()) {
90 resolvedTokens.remove(startOffset - 1, length);
91 resolvedTokens.insert(startOffset - 1, tokens);
92 return tokens.size();
93 }
94 }
95
96 // Fallback on default value if present
97 if (!commaLocation || m_cycleDetected) {
98 resolvedTokens.clear();
99 return 0;
100 }
101
102 // Move the tokens to the beginning of the variable reference
103 unsigned defaultValueOffset = commaLocation + 1;
Timothy Loh 2015/10/28 05:12:41 defaultValueStart?
leviw_travelin_and_unemployed 2015/10/30 21:41:16 Sure :)
104 unsigned defaultValueLength = end - commaLocation - 1;
Timothy Loh 2015/10/28 05:12:42 end - defaultValueStart
105 for (unsigned i = 0; i < defaultValueLength; ++i)
106 resolvedTokens[varFunctionPosition + i] = resolvedTokens[defaultValueOff set + i];
107 resolvedTokens.remove(varFunctionPosition + defaultValueLength, length - def aultValueLength);
108
109 resolveVariableReferencesFromTokens(resolvedTokens);
110
111 return resolvedTokens.size();
112 }
113
114 void CSSVariableResolver::resolveVariableReferencesFromTokens(Vector<CSSParserTo ken>& tokens)
115 {
116 for (unsigned i = 0; i < tokens.size(); ++i) {
117 if (tokens[i].functionId() == CSSValueVar) {
118 unsigned validTokens = resolveVariableTokensRecursive(tokens, i + 1) ;
119 if (validTokens < 1 || m_cycleDetected) {
120 tokens.clear();
121 break;
122 }
123 i += validTokens - 1;
124 }
125 }
126 }
127
128 void CSSVariableResolver::resolveAndApplyVariableReferences(StyleResolverState& state, CSSPropertyID id, const CSSVariableReferenceValue& value)
129 {
130 // TODO(leviw): This should be a stack
131 Vector<CSSParserToken> tokens = value.variableDataValue()->tokens();
132
133 CSSVariableResolver resolver(state.style()->variables());
134
135 resolver.resolveVariableReferencesFromTokens(tokens);
136
137 if (!tokens.size())
138 return;
139
140 CSSParserContext context(HTMLStandardMode, 0);
141
142 WillBeHeapVector<CSSProperty, 256> parsedProperties;
143
144 CSSPropertyParser::parseValue(id, false, CSSParserTokenRange(tokens), contex t, parsedProperties, StyleRule::Type::Style);
145
146 unsigned parsedPropertiesCount = parsedProperties.size();
147 for (unsigned i = 0; i < parsedPropertiesCount; ++i)
148 StyleBuilder::applyProperty(parsedProperties[i].id(), state, parsedPrope rties[i].value());
149 }
150
151 void CSSVariableResolver::resolveVariableDefinitions(StyleVariableData* variable s)
152 {
153 if (!variables)
154 return;
155
156 for (auto& variable : variables->m_data) {
157 if (!variable.value->needsVariableResolution())
158 continue;
159 Vector<CSSParserToken> resolvedTokens(variable.value->tokens());
160
161 CSSVariableResolver resolver(variables, variable.key);
162 resolver.resolveVariableReferencesFromTokens(resolvedTokens);
163
164 variable.value = CSSVariableData::createResolved(resolvedTokens);
165 }
166 }
167
168 CSSVariableResolver::CSSVariableResolver(StyleVariableData* styleVariableData)
169 : m_styleVariableData(styleVariableData)
170 , m_cycleDetected(false)
171 {
172 }
173
174 CSSVariableResolver::CSSVariableResolver(StyleVariableData* styleVariableData, A tomicString& variable)
175 : m_styleVariableData(styleVariableData)
176 , m_cycleDetected(false)
177 {
178 m_variablesSeen.add(variable);
179 }
180
181 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698