source: webkit/trunk/Source/WebCore/css/parser/CSSParserToken.cpp

Last change on this file was 292150, checked in by [email protected], 3 years ago

Implement units for CSS Typed OM
https://bugs.webkit.org/show_bug.cgi?id=238532

Patch by Alex Christensen <[email protected]> on 2022-03-31
Reviewed by Simon Fraser.

LayoutTests/imported/w3c:

  • web-platform-tests/css/css-typed-om/stylevalue-serialization/cssUnitValue.tentative-expected.txt:
  • web-platform-tests/css/css-typed-om/stylevalue-subclasses/numeric-objects/add-two-types.tentative-expected.txt:
  • web-platform-tests/css/css-typed-om/stylevalue-subclasses/numeric-objects/arithmetic.tentative-expected.txt:
  • web-platform-tests/css/css-typed-om/stylevalue-subclasses/numeric-objects/create-a-type.tentative-expected.txt:
  • web-platform-tests/css/css-typed-om/stylevalue-subclasses/numeric-objects/cssMathInvert-type-expected.txt:
  • web-platform-tests/css/css-typed-om/stylevalue-subclasses/numeric-objects/cssMathNegate-type-expected.txt:
  • web-platform-tests/css/css-typed-om/stylevalue-subclasses/numeric-objects/cssMathValue.tentative-expected.txt:
  • web-platform-tests/css/css-typed-om/stylevalue-subclasses/numeric-objects/cssUnitValue-expected.txt:
  • web-platform-tests/css/css-typed-om/stylevalue-subclasses/numeric-objects/cssnumericvalue-multiply-two-types.tentative-expected.txt:
  • web-platform-tests/css/css-typed-om/stylevalue-subclasses/numeric-objects/to.tentative-expected.txt:

Source/WebCore:

This feature is off by default and this part is covered by WPT tests.

  • css/typedom/CSSNumericFactory.h:
  • css/typedom/CSSNumericValue.cpp:

(WebCore::negate):
(WebCore::invert):
(WebCore::operationOnValuesOfSameUnit):
(WebCore::CSSNumericValue::addInternal):
(WebCore::CSSNumericValue::add):
(WebCore::CSSNumericValue::sub):
(WebCore::CSSNumericValue::multiplyInternal):
(WebCore::CSSNumericValue::mul):
(WebCore::CSSNumericValue::to):
(WebCore::CSSNumericValue::toSum):
(WebCore::CSSNumericValue::type): Deleted.

  • css/typedom/CSSNumericValue.h:

(WebCore::CSSNumericValue::type const):
(WebCore::CSSNumericValue::CSSNumericValue):

  • css/typedom/CSSUnitValue.cpp:

(WebCore::numericType):
(WebCore::parseUnit):
(WebCore::CSSUnitValue::unit const):
(WebCore::CSSUnitValue::unitSerialization const):
(WebCore::CSSUnitValue::create):
(WebCore::CSSUnitValue::CSSUnitValue):

  • css/typedom/CSSUnitValue.h:
  • css/typedom/numeric/CSSMathInvert.cpp:

(WebCore::negatedType):
(WebCore::CSSMathInvert::CSSMathInvert):

  • css/typedom/numeric/CSSMathNegate.cpp:

(WebCore::copyType):
(WebCore::CSSMathNegate::CSSMathNegate):

  • css/typedom/numeric/CSSMathProduct.cpp:

(WebCore::multiplyTypes):
(WebCore::CSSMathProduct::create):
(WebCore::CSSMathProduct::CSSMathProduct):
(WebCore::CSSMathProduct::values const): Deleted.

  • css/typedom/numeric/CSSMathProduct.h:
  • css/typedom/numeric/CSSMathSum.cpp:

(WebCore::addTypes):
(WebCore::CSSMathSum::create):
(WebCore::CSSMathSum::CSSMathSum):

  • css/typedom/numeric/CSSMathSum.h:
  • css/typedom/numeric/CSSMathValue.h:

(WebCore::CSSMathValue::CSSMathValue):

  • css/typedom/numeric/CSSNumericArray.cpp:

(WebCore::CSSNumericArray::create):

  • css/typedom/numeric/CSSNumericBaseType.h:

(WebCore::eachBaseType):
(WebCore::debugString):
(): Deleted.

  • css/typedom/numeric/CSSNumericType.h:

(WebCore::CSSNumericType::operator== const):
(WebCore::CSSNumericType::valueForType):
(WebCore::CSSNumericType::applyPercentHint):
(WebCore::CSSNumericType::debugString const):
(): Deleted.

  • css/typedom/numeric/CSSNumericType.idl:
File size: 22.9 KB
Line 
1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Copyright (C) 2016-2021 Apple Inc. All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8// * Redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above
11// copyright notice, this list of conditions and the following disclaimer
12// in the documentation and/or other materials provided with the
13// distribution.
14// * Neither the name of Google Inc. nor the names of its
15// contributors may be used to endorse or promote products derived from
16// this software without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30#include "config.h"
31#include "CSSParserToken.h"
32
33#include "CSSMarkup.h"
34#include "CSSPrimitiveValue.h"
35#include "CSSPropertyParser.h"
36#include "RuntimeEnabledFeatures.h"
37#include <limits.h>
38#include <wtf/HexNumber.h>
39#include <wtf/text/StringBuilder.h>
40
41namespace WebCore {
42
43template<typename CharacterType>
44CSSUnitType cssPrimitiveValueUnitFromTrie(const CharacterType* data, unsigned length)
45{
46 ASSERT(data);
47 switch (length) {
48 case 1:
49 switch (toASCIILower(data[0])) {
50 case 'q':
51 return CSSUnitType::CSS_Q;
52 case 's':
53 return CSSUnitType::CSS_S;
54 case 'x':
55 return CSSUnitType::CSS_X;
56 }
57 break;
58 case 2:
59 switch (toASCIILower(data[0])) {
60 case 'c':
61 switch (toASCIILower(data[1])) {
62 case 'h':
63 return CSSUnitType::CSS_CHS;
64 case 'm':
65 return CSSUnitType::CSS_CM;
66 }
67 break;
68 case 'e':
69 switch (toASCIILower(data[1])) {
70 case 'm':
71 return CSSUnitType::CSS_EMS;
72 case 'x':
73 return CSSUnitType::CSS_EXS;
74 }
75 break;
76 case 'f':
77 if (toASCIILower(data[1]) == 'r')
78 return CSSUnitType::CSS_FR;
79 break;
80 case 'h':
81 if (toASCIILower(data[1]) == 'z')
82 return CSSUnitType::CSS_HZ;
83 break;
84 case 'i':
85 switch (toASCIILower(data[1])) {
86 case 'c':
87 return CSSUnitType::CSS_IC;
88 case 'n':
89 return CSSUnitType::CSS_IN;
90 }
91 break;
92 case 'l':
93 if (toASCIILower(data[1]) == 'h' && RuntimeEnabledFeatures::sharedFeatures().lineHeightUnitsEnabled())
94 return CSSUnitType::CSS_LHS;
95 break;
96 case 'm':
97 switch (toASCIILower(data[1])) {
98 case 'm':
99 return CSSUnitType::CSS_MM;
100 case 's':
101 return CSSUnitType::CSS_MS;
102 }
103 break;
104 case 'p':
105 switch (toASCIILower(data[1])) {
106 case 'c':
107 return CSSUnitType::CSS_PC;
108 case 't':
109 return CSSUnitType::CSS_PT;
110 case 'x':
111 return CSSUnitType::CSS_PX;
112 }
113 break;
114 case 'v':
115 switch (toASCIILower(data[1])) {
116 case 'b':
117 return CSSUnitType::CSS_VB;
118 case 'h':
119 return CSSUnitType::CSS_VH;
120 case 'i':
121 return CSSUnitType::CSS_VI;
122 case 'w':
123 return CSSUnitType::CSS_VW;
124 }
125 break;
126 }
127 break;
128 case 3:
129 switch (toASCIILower(data[0])) {
130 case 'c':
131 if (toASCIILower(data[1]) == 'q') {
132 switch (toASCIILower(data[2])) {
133 case 'b':
134 return CSSUnitType::CSS_CQB;
135 case 'h':
136 return CSSUnitType::CSS_CQH;
137 case 'i':
138 return CSSUnitType::CSS_CQI;
139 case 'w':
140 return CSSUnitType::CSS_CQW;
141 }
142 }
143 break;
144 case 'd':
145 switch (toASCIILower(data[1])) {
146 case 'e':
147 if (toASCIILower(data[2]) == 'g')
148 return CSSUnitType::CSS_DEG;
149 break;
150 case 'p':
151 if (toASCIILower(data[2]) == 'i')
152 return CSSUnitType::CSS_DPI;
153 break;
154 case 'v':
155 switch (toASCIILower(data[2])) {
156 case 'b':
157 return CSSUnitType::CSS_DVB;
158 case 'h':
159 return CSSUnitType::CSS_DVH;
160 case 'i':
161 return CSSUnitType::CSS_DVI;
162 case 'w':
163 return CSSUnitType::CSS_DVW;
164 }
165 break;
166 }
167 break;
168 case 'l':
169 if (toASCIILower(data[1]) == 'v') {
170 switch (toASCIILower(data[2])) {
171 case 'b':
172 return CSSUnitType::CSS_LVB;
173 case 'h':
174 return CSSUnitType::CSS_LVH;
175 case 'i':
176 return CSSUnitType::CSS_LVI;
177 case 'w':
178 return CSSUnitType::CSS_LVW;
179 }
180 }
181 break;
182 case 'k':
183 if (toASCIILower(data[1]) == 'h' && toASCIILower(data[2]) == 'z')
184 return CSSUnitType::CSS_KHZ;
185 break;
186 case 'r':
187 switch (toASCIILower(data[1])) {
188 case 'a':
189 if (toASCIILower(data[2]) == 'd')
190 return CSSUnitType::CSS_RAD;
191 break;
192 case 'e':
193 if (toASCIILower(data[2]) == 'm')
194 return CSSUnitType::CSS_REMS;
195 break;
196 case 'l':
197 if (toASCIILower(data[2]) == 'h' && RuntimeEnabledFeatures::sharedFeatures().lineHeightUnitsEnabled())
198 return CSSUnitType::CSS_RLHS;
199 break;
200 }
201 break;
202 case 's':
203 if (toASCIILower(data[1]) == 'v') {
204 switch (toASCIILower(data[2])) {
205 case 'b':
206 return CSSUnitType::CSS_SVB;
207 case 'h':
208 return CSSUnitType::CSS_SVH;
209 case 'i':
210 return CSSUnitType::CSS_SVI;
211 case 'w':
212 return CSSUnitType::CSS_SVW;
213 }
214 }
215 break;
216 }
217 break;
218 case 4:
219 switch (toASCIILower(data[0])) {
220 case 'd':
221 switch (toASCIILower(data[1])) {
222 case 'p':
223 switch (toASCIILower(data[2])) {
224 case 'c':
225 if (toASCIILower(data[3]) == 'm')
226 return CSSUnitType::CSS_DPCM;
227 break;
228 case 'p':
229 if (toASCIILower(data[3]) == 'x')
230 return CSSUnitType::CSS_DPPX;
231 break;
232 }
233 break;
234 }
235 break;
236 case 'g':
237 if (toASCIILower(data[1]) == 'r' && toASCIILower(data[2]) == 'a' && toASCIILower(data[3]) == 'd')
238 return CSSUnitType::CSS_GRAD;
239 break;
240 case 't':
241 if (toASCIILower(data[1]) == 'u' && toASCIILower(data[2]) == 'r' && toASCIILower(data[3]) == 'n')
242 return CSSUnitType::CSS_TURN;
243 break;
244 case 'v':
245 switch (toASCIILower(data[1])) {
246 case 'm':
247 switch (toASCIILower(data[2])) {
248 case 'a':
249 if (toASCIILower(data[3]) == 'x')
250 return CSSUnitType::CSS_VMAX;
251 break;
252 case 'i':
253 if (toASCIILower(data[3]) == 'n')
254 return CSSUnitType::CSS_VMIN;
255 break;
256 }
257 break;
258 }
259 break;
260 }
261 break;
262 case 5:
263 switch (toASCIILower(data[0])) {
264 case '_':
265 if (toASCIILower(data[1]) == '_' && toASCIILower(data[2]) == 'q' && toASCIILower(data[3]) == 'e' && toASCIILower(data[4]) == 'm')
266 return CSSUnitType::CSS_QUIRKY_EMS;
267 break;
268 case 'c':
269 if (toASCIILower(data[1]) == 'q' && toASCIILower(data[2]) == 'm') {
270 switch (toASCIILower(data[3])) {
271 case 'a':
272 if (toASCIILower(data[4]) == 'x')
273 return CSSUnitType::CSS_CQMAX;
274 break;
275 case 'i':
276 if (toASCIILower(data[4]) == 'n')
277 return CSSUnitType::CSS_CQMIN;
278 break;
279 }
280 }
281 break;
282 case 'd':
283 if (toASCIILower(data[1]) == 'v' && toASCIILower(data[2]) == 'm') {
284 switch (toASCIILower(data[3])) {
285 case 'a':
286 if (toASCIILower(data[4]) == 'x')
287 return CSSUnitType::CSS_DVMAX;
288 break;
289 case 'i':
290 if (toASCIILower(data[4]) == 'n')
291 return CSSUnitType::CSS_DVMIN;
292 break;
293 }
294 }
295 break;
296 case 'l':
297 if (toASCIILower(data[1]) == 'v' && toASCIILower(data[2]) == 'm') {
298 switch (toASCIILower(data[3])) {
299 case 'a':
300 if (toASCIILower(data[4]) == 'x')
301 return CSSUnitType::CSS_LVMAX;
302 break;
303 case 'i':
304 if (toASCIILower(data[4]) == 'n')
305 return CSSUnitType::CSS_LVMIN;
306 break;
307 }
308 }
309 break;
310 case 's':
311 if (toASCIILower(data[1]) == 'v' && toASCIILower(data[2]) == 'm') {
312 switch (toASCIILower(data[3])) {
313 case 'a':
314 if (toASCIILower(data[4]) == 'x')
315 return CSSUnitType::CSS_SVMAX;
316 break;
317 case 'i':
318 if (toASCIILower(data[4]) == 'n')
319 return CSSUnitType::CSS_SVMIN;
320 break;
321 }
322 }
323 break;
324 }
325 break;
326 }
327 return CSSUnitType::CSS_UNKNOWN;
328}
329
330CSSUnitType CSSParserToken::stringToUnitType(StringView stringView)
331{
332 if (stringView.is8Bit())
333 return cssPrimitiveValueUnitFromTrie(stringView.characters8(), stringView.length());
334 return cssPrimitiveValueUnitFromTrie(stringView.characters16(), stringView.length());
335}
336
337CSSParserToken::CSSParserToken(CSSParserTokenType type, BlockType blockType)
338 : m_type(type)
339 , m_blockType(blockType)
340{
341}
342
343// Just a helper used for Delimiter tokens.
344CSSParserToken::CSSParserToken(CSSParserTokenType type, UChar c)
345 : m_type(type)
346 , m_blockType(NotBlock)
347 , m_delimiter(c)
348{
349 ASSERT(m_type == DelimiterToken);
350}
351
352CSSParserToken::CSSParserToken(CSSParserTokenType type, StringView value, BlockType blockType)
353 : m_type(type)
354 , m_blockType(blockType)
355{
356 initValueFromStringView(value);
357 m_id = -1;
358}
359
360CSSParserToken::CSSParserToken(double numericValue, NumericValueType numericValueType, NumericSign sign, StringView originalText)
361 : m_type(NumberToken)
362 , m_blockType(NotBlock)
363 , m_numericValueType(numericValueType)
364 , m_numericSign(sign)
365 , m_unit(static_cast<unsigned>(CSSUnitType::CSS_NUMBER))
366 , m_numericValue(numericValue)
367{
368 initValueFromStringView(originalText);
369}
370
371CSSParserToken::CSSParserToken(HashTokenType type, StringView value)
372 : m_type(HashToken)
373 , m_blockType(NotBlock)
374 , m_hashTokenType(type)
375{
376 initValueFromStringView(value);
377}
378
379static StringView mergeIfAdjacent(StringView a, StringView b)
380{
381 if (a.is8Bit() && b.is8Bit()) {
382 auto characters = a.characters8();
383 if (characters + a.length() == b.characters8())
384 return { characters, a.length() + b.length() };
385 } else if (!a.is8Bit() && !b.is8Bit()) {
386 auto characters = a.characters16();
387 if (characters + a.length() == b.characters16())
388 return { characters, a.length() + b.length() };
389 }
390 return { };
391}
392
393void CSSParserToken::convertToDimensionWithUnit(StringView unit)
394{
395 ASSERT(m_type == NumberToken);
396 auto originalNumberText = originalText();
397 auto originalNumberTextLength = originalNumberText.length();
398 auto string = unit;
399 if (originalNumberTextLength && originalNumberTextLength < 16) {
400 if (auto merged = mergeIfAdjacent(originalNumberText, unit))
401 string = merged;
402 }
403 m_type = DimensionToken;
404 m_unit = static_cast<unsigned>(stringToUnitType(unit));
405 m_nonUnitPrefixLength = string == unit ? 0 : originalNumberTextLength;
406 initValueFromStringView(string);
407}
408
409void CSSParserToken::convertToPercentage()
410{
411 ASSERT(m_type == NumberToken);
412 m_type = PercentageToken;
413 m_unit = static_cast<unsigned>(CSSUnitType::CSS_PERCENTAGE);
414}
415
416StringView CSSParserToken::originalText() const
417{
418 ASSERT(m_type == NumberToken || m_type == DimensionToken);
419 return value();
420}
421
422StringView CSSParserToken::unitString() const
423{
424 ASSERT(m_type == DimensionToken);
425 return value().substring(m_nonUnitPrefixLength);
426}
427
428UChar CSSParserToken::delimiter() const
429{
430 ASSERT(m_type == DelimiterToken);
431 return m_delimiter;
432}
433
434NumericSign CSSParserToken::numericSign() const
435{
436 // This is valid for DimensionToken and PercentageToken, but only used
437 // in <an+b> parsing on NumberTokens.
438 ASSERT(m_type == NumberToken);
439 return static_cast<NumericSign>(m_numericSign);
440}
441
442NumericValueType CSSParserToken::numericValueType() const
443{
444 ASSERT(m_type == NumberToken || m_type == PercentageToken || m_type == DimensionToken);
445 return static_cast<NumericValueType>(m_numericValueType);
446}
447
448double CSSParserToken::numericValue() const
449{
450 ASSERT(m_type == NumberToken || m_type == PercentageToken || m_type == DimensionToken);
451 return m_numericValue;
452}
453
454CSSPropertyID CSSParserToken::parseAsCSSPropertyID() const
455{
456 ASSERT(m_type == IdentToken);
457 return cssPropertyID(value());
458}
459
460CSSValueID CSSParserToken::id() const
461{
462 if (m_type != IdentToken)
463 return CSSValueInvalid;
464 if (m_id < 0)
465 m_id = cssValueKeywordID(value());
466 return static_cast<CSSValueID>(m_id);
467}
468
469CSSValueID CSSParserToken::functionId() const
470{
471 if (m_type != FunctionToken)
472 return CSSValueInvalid;
473 if (m_id < 0)
474 m_id = cssValueKeywordID(value());
475 return static_cast<CSSValueID>(m_id);
476}
477
478bool CSSParserToken::hasStringBacking() const
479{
480 switch (type()) {
481 case AtKeywordToken:
482 case DimensionToken:
483 case FunctionToken:
484 case HashToken:
485 case IdentToken:
486 case NumberToken:
487 case PercentageToken:
488 case StringToken:
489 case UrlToken:
490 return true;
491 case BadStringToken:
492 case BadUrlToken:
493 case CDCToken:
494 case CDOToken:
495 case ColonToken:
496 case ColumnToken:
497 case CommaToken:
498 case CommentToken:
499 case DashMatchToken:
500 case DelimiterToken:
501 case EOFToken:
502 case IncludeMatchToken:
503 case LeftBraceToken:
504 case LeftBracketToken:
505 case LeftParenthesisToken:
506 case PrefixMatchToken:
507 case RightBraceToken:
508 case RightBracketToken:
509 case RightParenthesisToken:
510 case SemicolonToken:
511 case SubstringMatchToken:
512 case SuffixMatchToken:
513 case WhitespaceToken:
514 return false;
515 }
516 ASSERT_NOT_REACHED();
517 return false;
518}
519
520CSSParserToken CSSParserToken::copyWithUpdatedString(StringView string) const
521{
522 ASSERT(value() == string);
523 CSSParserToken copy(*this);
524 copy.initValueFromStringView(string);
525 return copy;
526}
527
528bool CSSParserToken::operator==(const CSSParserToken& other) const
529{
530 if (m_type != other.m_type)
531 return false;
532 switch (m_type) {
533 case DelimiterToken:
534 return delimiter() == other.delimiter();
535 case HashToken:
536 if (m_hashTokenType != other.m_hashTokenType)
537 return false;
538 FALLTHROUGH;
539 case IdentToken:
540 case FunctionToken:
541 case StringToken:
542 case UrlToken:
543 return value() == other.value();
544 case DimensionToken:
545 if (unitString() != other.unitString())
546 return false;
547 FALLTHROUGH;
548 case NumberToken:
549 case PercentageToken:
550 return m_numericSign == other.m_numericSign && m_numericValue == other.m_numericValue && m_numericValueType == other.m_numericValueType;
551 default:
552 return true;
553 }
554}
555
556struct NextTokenNeedsCommentBuilder {
557 constexpr NextTokenNeedsCommentBuilder(std::initializer_list<CSSParserTokenType> tokens)
558 {
559 for (auto token : tokens)
560 buffer[token] = true;
561 }
562
563 std::array<bool, numberOfCSSParserTokenTypes> buffer { false };
564};
565
566void CSSParserToken::serialize(StringBuilder& builder, const CSSParserToken* nextToken) const
567{
568 // This is currently only used for @supports CSSOM. To keep our implementation
569 // simple we handle some of the edge cases incorrectly (see comments below).
570 auto appendCommentIfNeeded = [&] (const NextTokenNeedsCommentBuilder& tokensNeedingComment, auto... delimitersNeedingComment) {
571 if (!nextToken)
572 return;
573
574 CSSParserTokenType nextType = nextToken->type();
575 if (tokensNeedingComment.buffer[nextType]) {
576 builder.append("/**/");
577 return;
578 }
579
580 if (nextType == DelimiterToken && ((delimitersNeedingComment == nextToken->delimiter()) || ... || false)) {
581 builder.append("/**/");
582 return;
583 }
584 };
585
586 switch (type()) {
587 case IdentToken:
588 serializeIdentifier(value().toString(), builder);
589 appendCommentIfNeeded({ IdentToken, FunctionToken, UrlToken, BadUrlToken, NumberToken, PercentageToken, DimensionToken, CDCToken, LeftParenthesisToken }, '-');
590 break;
591 case FunctionToken:
592 serializeIdentifier(value().toString(), builder);
593 builder.append('(');
594 break;
595 case AtKeywordToken:
596 builder.append('@');
597 serializeIdentifier(value().toString(), builder);
598 appendCommentIfNeeded({ IdentToken, FunctionToken, UrlToken, BadUrlToken, NumberToken, PercentageToken, DimensionToken, CDCToken }, '-');
599 break;
600 case HashToken:
601 builder.append('#');
602 serializeIdentifier(value().toString(), builder, (getHashTokenType() == HashTokenUnrestricted));
603 appendCommentIfNeeded({ IdentToken, FunctionToken, UrlToken, BadUrlToken, NumberToken, PercentageToken, DimensionToken, CDCToken }, '-');
604 break;
605 case UrlToken:
606 builder.append("url(");
607 serializeIdentifier(value().toString(), builder);
608 builder.append(')');
609 break;
610 case DelimiterToken:
611 switch (delimiter()) {
612 case '\\':
613 builder.append("\\\n");
614 break;
615
616 case '#':
617 case '-':
618 builder.append(delimiter());
619 appendCommentIfNeeded({ IdentToken, FunctionToken, UrlToken, BadUrlToken, NumberToken, PercentageToken, DimensionToken }, '-');
620 break;
621
622 case '@':
623 builder.append('@');
624 appendCommentIfNeeded({ IdentToken, FunctionToken, UrlToken, BadUrlToken }, '-');
625 break;
626
627 case '.':
628 case '+':
629 builder.append(delimiter());
630 appendCommentIfNeeded({ NumberToken, PercentageToken, DimensionToken });
631 break;
632
633 case '/':
634 builder.append('/');
635 // Weirdly Clang errors if you try to use the fold expression in buildNextTokenNeedsCommentTable() because the true value is unused.
636 // So we just build the table by hand here instead. See: rdar://69710661
637 appendCommentIfNeeded({ }, '*');
638 break;
639
640 default:
641 builder.append(delimiter());
642 break;
643 }
644 break;
645 case NumberToken:
646 // These won't properly preserve the NumericValueType flag.
647 if (m_numericSign == PlusSign)
648 builder.append('+');
649 builder.append(numericValue());
650 appendCommentIfNeeded({ IdentToken, FunctionToken, UrlToken, BadUrlToken, NumberToken, PercentageToken, DimensionToken }, '%');
651 break;
652 case PercentageToken:
653 builder.append(numericValue(), '%');
654 break;
655 case DimensionToken:
656 // This will incorrectly serialize e.g. 4e3e2 as 4000e2.
657 builder.append(numericValue());
658 serializeIdentifier(unitString().toString(), builder);
659 appendCommentIfNeeded({ IdentToken, FunctionToken, UrlToken, BadUrlToken, NumberToken, PercentageToken, DimensionToken, CDCToken }, '-');
660 break;
661 case StringToken:
662 serializeString(value().toString(), builder);
663 break;
664
665 case IncludeMatchToken:
666 builder.append("~=");
667 break;
668 case DashMatchToken:
669 builder.append("|=");
670 break;
671 case PrefixMatchToken:
672 builder.append("^=");
673 break;
674 case SuffixMatchToken:
675 builder.append("$=");
676 break;
677 case SubstringMatchToken:
678 builder.append("*=");
679 break;
680 case ColumnToken:
681 builder.append("||");
682 break;
683 case CDOToken:
684 builder.append("<!--");
685 break;
686 case CDCToken:
687 builder.append("-->");
688 break;
689 case BadStringToken:
690 builder.append("'\n");
691 break;
692 case BadUrlToken:
693 builder.append("url(()");
694 break;
695 case WhitespaceToken:
696 builder.append(' ');
697 break;
698 case ColonToken:
699 builder.append(':');
700 break;
701 case SemicolonToken:
702 builder.append(';');
703 break;
704 case CommaToken:
705 builder.append(',');
706 break;
707 case LeftParenthesisToken:
708 builder.append('(');
709 break;
710 case RightParenthesisToken:
711 builder.append(')');
712 break;
713 case LeftBracketToken:
714 builder.append('[');
715 break;
716 case RightBracketToken:
717 builder.append(']');
718 break;
719 case LeftBraceToken:
720 builder.append('{');
721 break;
722 case RightBraceToken:
723 builder.append('}');
724 break;
725
726 case EOFToken:
727 case CommentToken:
728 ASSERT_NOT_REACHED();
729 break;
730 }
731}
732
733} // namespace WebCore
Note: See TracBrowser for help on using the repository browser.