Chromium Code Reviews| OLD | NEW |
|---|---|
| (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/parser/CSSVariableParser.h" | |
| 7 | |
| 8 #include "core/css/CSSCustomVariableValue.h" | |
| 9 #include "core/css/parser/CSSParserTokenRange.h" | |
| 10 #include "core/css/parser/CSSParserValues.h" | |
| 11 | |
| 12 namespace blink { | |
| 13 | |
| 14 static bool isValidVariableName(const CSSParserToken& token) | |
| 15 { | |
|
Timothy Loh
2015/08/25 09:21:10
Probably a good idea to check the token type is an
| |
| 16 CSSParserString value = token.value(); | |
| 17 return value.length() >= 2 && value[0] == '-' && value[0] == value[1]; | |
|
Timothy Loh
2015/08/25 09:21:11
err.. value[1] == '-'?
| |
| 18 } | |
| 19 | |
| 20 static bool isValidVariableReference(CSSParserTokenRange& range) | |
|
Timothy Loh
2015/08/25 09:21:10
Use consumeBlock in the calling function and make
| |
| 21 { | |
| 22 bool foundVariableIdentToken = false; | |
| 23 bool foundComma = false; | |
| 24 bool contentAfterComma = false; | |
| 25 | |
| 26 // TODO(leviw): Use CSSParserToken::BlockType signals instead of checking fo r these directly. | |
| 27 int parenthesisCount = 0; | |
| 28 int braceCount = 0; | |
| 29 int bracketCount = 0; | |
| 30 while (!range.atEnd()) { | |
| 31 const CSSParserToken& token = range.consume(); | |
| 32 | |
| 33 if (!foundVariableIdentToken) { | |
|
Timothy Loh
2015/08/25 09:21:10
This would be easier without the state machine loo
| |
| 34 if (token.type() == IdentToken) { | |
| 35 if (!isValidVariableName(token)) | |
| 36 return false; | |
| 37 foundVariableIdentToken = true; | |
| 38 } else if (token.type() != WhitespaceToken) { | |
| 39 return false; | |
| 40 } | |
| 41 continue; | |
| 42 } | |
| 43 | |
| 44 if (!foundComma) { | |
| 45 if (token.type() == CommaToken) | |
| 46 foundComma = true; | |
| 47 else if (token.type() == RightParenthesisToken) | |
| 48 return true; | |
| 49 else if (token.type() != WhitespaceToken) | |
| 50 return false; | |
| 51 continue; | |
| 52 } | |
| 53 | |
| 54 if (!contentAfterComma) { | |
| 55 if (token.type() == RightParenthesisToken) | |
| 56 return false; | |
| 57 contentAfterComma = true; | |
| 58 } | |
| 59 | |
| 60 switch (token.type()) { | |
| 61 case DelimiterToken: | |
| 62 if (token.delimiter() == '!' && !parenthesisCount && !bracketCount & & !braceCount) | |
| 63 return false; | |
| 64 break; | |
| 65 case FunctionToken: | |
| 66 case LeftParenthesisToken: | |
| 67 parenthesisCount++; | |
| 68 break; | |
| 69 case RightParenthesisToken: | |
| 70 if (!parenthesisCount) | |
| 71 return true; | |
| 72 parenthesisCount--; | |
| 73 break; | |
| 74 case RightBraceToken: | |
| 75 if (!braceCount) | |
| 76 return false; | |
| 77 braceCount--; | |
| 78 break; | |
| 79 case LeftBraceToken: | |
| 80 braceCount++; | |
| 81 break; | |
| 82 case RightBracketToken: | |
| 83 if (!bracketCount) | |
| 84 return false; | |
| 85 bracketCount--; | |
| 86 break; | |
| 87 case LeftBracketToken: | |
| 88 bracketCount++; | |
| 89 break; | |
| 90 case BadStringToken: | |
| 91 case BadUrlToken: | |
| 92 return false; | |
| 93 case CommentToken: | |
| 94 case EOFToken: | |
| 95 ASSERT_NOT_REACHED(); | |
| 96 case SemicolonToken: | |
| 97 if (!parenthesisCount && !bracketCount && !braceCount) | |
| 98 return false; | |
| 99 break; | |
| 100 default: | |
| 101 break; | |
| 102 } | |
| 103 } | |
| 104 return foundVariableIdentToken && (!foundComma || contentAfterComma); | |
| 105 } | |
| 106 | |
| 107 static CSSValueID classifyVariableRange(CSSParserTokenRange& originalRange, bool & hasReferences) | |
|
Timothy Loh
2015/08/25 09:21:11
CSSParserTokenRange& originalRange -> CSSParserTok
| |
| 108 { | |
| 109 hasReferences = false; | |
| 110 CSSParserTokenRange range = originalRange; | |
| 111 | |
| 112 int parenthesisCount = 0; | |
| 113 int braceCount = 0; | |
| 114 int bracketCount = 0; | |
| 115 | |
| 116 range.consumeWhitespace(); | |
| 117 if (range.peek().type() == IdentToken) { | |
| 118 const CSSParserToken& ident = range.consumeIncludingWhitespace(); | |
| 119 if (range.atEnd()) { | |
| 120 if (ident.valueEqualsIgnoringCase("inherit")) | |
| 121 return CSSValueInherit; | |
| 122 if (ident.valueEqualsIgnoringCase("initial")) | |
| 123 return CSSValueInitial; | |
| 124 if (ident.valueEqualsIgnoringCase("unset")) | |
| 125 return CSSValueUnset; | |
| 126 } | |
| 127 } | |
| 128 | |
| 129 // TODO(leviw): Use consumeBlock to keep track of nesting instead of doing i t directly here. | |
| 130 while (!range.atEnd()) { | |
| 131 const CSSParserToken& token = range.consume(); | |
| 132 switch (token.type()) { | |
| 133 case FunctionToken: | |
| 134 if (token.valueEqualsIgnoringCase("var")) { | |
| 135 if (!isValidVariableReference(range)) | |
| 136 return CSSValueInvalid; // Bail if any references are invali d | |
| 137 hasReferences = true; | |
| 138 } else { | |
| 139 parenthesisCount++; | |
| 140 } | |
| 141 break; | |
| 142 case CommentToken: | |
| 143 case EOFToken: | |
| 144 ASSERT_NOT_REACHED(); | |
| 145 case DelimiterToken: { | |
| 146 if (token.delimiter() == '!' && !parenthesisCount && !bracketCount & & !braceCount) | |
| 147 return CSSValueInvalid; | |
| 148 break; | |
| 149 } | |
| 150 case RightParenthesisToken: | |
| 151 if (!parenthesisCount) | |
| 152 return CSSValueInvalid; | |
| 153 parenthesisCount--; | |
| 154 break; | |
| 155 case LeftParenthesisToken: | |
| 156 parenthesisCount++; | |
| 157 break; | |
| 158 case RightBraceToken: | |
| 159 if (!braceCount) | |
| 160 return CSSValueInvalid; | |
| 161 braceCount--; | |
| 162 break; | |
| 163 case LeftBraceToken: | |
| 164 braceCount++; | |
| 165 break; | |
| 166 case RightBracketToken: | |
| 167 if (!bracketCount) | |
| 168 return CSSValueInvalid; | |
| 169 bracketCount--; | |
| 170 break; | |
| 171 case LeftBracketToken: | |
| 172 bracketCount++; | |
| 173 break; | |
| 174 case BadStringToken: | |
| 175 case BadUrlToken: | |
| 176 return CSSValueInvalid; | |
| 177 case WhitespaceToken: | |
| 178 break; | |
| 179 case SemicolonToken: | |
| 180 if (!parenthesisCount && !bracketCount && !braceCount) | |
| 181 return CSSValueInvalid; | |
| 182 default: | |
| 183 break; | |
| 184 } | |
| 185 } | |
| 186 if (parenthesisCount) | |
| 187 return CSSValueInvalid; | |
| 188 return CSSValueInternalVariableValue; | |
| 189 } | |
| 190 | |
| 191 bool CSSVariableParser::containsValidVariableReferences(const CSSParserTokenRang e& originalRange) | |
|
Timothy Loh
2015/08/25 09:21:10
CSSParserTokenRange& originalRange -> CSSParserTok
| |
| 192 { | |
| 193 CSSParserTokenRange range = originalRange; | |
| 194 bool hasReferences; | |
| 195 CSSValueID type = classifyVariableRange(range, hasReferences); | |
| 196 return type == CSSValueInternalVariableValue && hasReferences; | |
| 197 } | |
| 198 | |
| 199 PassRefPtrWillBeRawPtr<CSSCustomVariableValue> CSSVariableParser::parseDeclarati onValue(const AtomicString& variableName, CSSParserTokenRange& originalRange) | |
|
Timothy Loh
2015/08/25 09:21:11
CSSParserTokenRange& originalRange -> CSSParserTok
| |
| 200 { | |
| 201 if (originalRange.atEnd()) | |
| 202 return nullptr; | |
| 203 | |
| 204 bool hasReferences; | |
| 205 CSSValueID type = classifyVariableRange(originalRange, hasReferences); | |
| 206 | |
| 207 if (type == CSSValueInvalid) | |
| 208 return nullptr; | |
| 209 if (type == CSSValueInternalVariableValue) | |
| 210 return CSSCustomVariableValue::create(variableName, CSSVariableData::cre ate(originalRange, hasReferences)); | |
| 211 return CSSCustomVariableValue::create(variableName, type); | |
| 212 } | |
| 213 | |
| 214 } // namespace blink | |
| OLD | NEW |