REGRESSION (Safari 10.1): When 'transition' contains -ms-transform, transform-origin...
[WebKit-https.git] / Source / WebCore / css / CSSComputedStyleDeclaration.cpp
1 /*
2  * Copyright (C) 2004 Zack Rusin <zack@kde.org>
3  * Copyright (C) 2004-2017 Apple Inc. All rights reserved.
4  * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
5  * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com>
6  * Copyright (C) 2011 Sencha, Inc. All rights reserved.
7  * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  * 02110-1301  USA
23  */
24
25 #include "config.h"
26 #include "CSSComputedStyleDeclaration.h"
27
28 #include "BasicShapeFunctions.h"
29 #include "BasicShapes.h"
30 #include "CSSAnimationController.h"
31 #include "CSSAnimationTriggerScrollValue.h"
32 #include "CSSAspectRatioValue.h"
33 #include "CSSBasicShapes.h"
34 #include "CSSBorderImage.h"
35 #include "CSSBorderImageSliceValue.h"
36 #include "CSSCustomPropertyValue.h"
37 #include "CSSFontFeatureValue.h"
38 #include "CSSFontStyleValue.h"
39 #include "CSSFontValue.h"
40 #include "CSSFontVariationValue.h"
41 #include "CSSFunctionValue.h"
42 #include "CSSLineBoxContainValue.h"
43 #include "CSSPrimitiveValue.h"
44 #include "CSSPrimitiveValueMappings.h"
45 #include "CSSPropertyNames.h"
46 #include "CSSPropertyParser.h"
47 #include "CSSReflectValue.h"
48 #include "CSSSelector.h"
49 #include "CSSShadowValue.h"
50 #include "CSSTimingFunctionValue.h"
51 #include "CSSValueList.h"
52 #include "CSSValuePool.h"
53 #include "ComposedTreeAncestorIterator.h"
54 #include "ContentData.h"
55 #include "CounterContent.h"
56 #include "CursorList.h"
57 #include "DeprecatedCSSOMValue.h"
58 #include "Document.h"
59 #include "ExceptionCode.h"
60 #include "FontSelectionValueInlines.h"
61 #include "FontTaggedSettings.h"
62 #include "HTMLFrameOwnerElement.h"
63 #include "NodeRenderStyle.h"
64 #include "Pair.h"
65 #include "PseudoElement.h"
66 #include "Rect.h"
67 #include "RenderBlock.h"
68 #include "RenderBox.h"
69 #include "RenderStyle.h"
70 #include "RuntimeEnabledFeatures.h"
71 #include "SVGElement.h"
72 #include "Settings.h"
73 #include "ShapeValue.h"
74 #include "StyleInheritedData.h"
75 #include "StyleProperties.h"
76 #include "StylePropertyShorthand.h"
77 #include "StylePropertyShorthandFunctions.h"
78 #include "StyleResolver.h"
79 #include "StyleScope.h"
80 #include "StyleScrollSnapPoints.h"
81 #include "Text.h"
82 #include "WebKitFontFamilyNames.h"
83 #include "WillChangeData.h"
84 #include <wtf/NeverDestroyed.h>
85 #include <wtf/text/StringBuilder.h>
86
87 #include "CSSGridLineNamesValue.h"
88 #include "CSSGridTemplateAreasValue.h"
89 #include "RenderGrid.h"
90
91 #if ENABLE(DASHBOARD_SUPPORT)
92 #include "DashboardRegion.h"
93 #endif
94
95 #if ENABLE(CSS_ANIMATIONS_LEVEL_2)
96 #include "AnimationTrigger.h"
97 #endif
98
99 namespace WebCore {
100
101 // List of all properties we know how to compute, omitting shorthands.
102 static const CSSPropertyID computedProperties[] = {
103     CSSPropertyAlt,
104     CSSPropertyAnimationDelay,
105     CSSPropertyAnimationDirection,
106     CSSPropertyAnimationDuration,
107     CSSPropertyAnimationFillMode,
108     CSSPropertyAnimationIterationCount,
109     CSSPropertyAnimationName,
110     CSSPropertyAnimationPlayState,
111     CSSPropertyAnimationTimingFunction,
112     CSSPropertyBackgroundAttachment,
113     CSSPropertyBackgroundBlendMode,
114     CSSPropertyBackgroundClip,
115     CSSPropertyBackgroundColor,
116     CSSPropertyBackgroundImage,
117     CSSPropertyBackgroundOrigin,
118     CSSPropertyBackgroundPosition, // more-specific background-position-x/y are non-standard
119     CSSPropertyBackgroundRepeat,
120     CSSPropertyBackgroundSize,
121     CSSPropertyBorderBottomColor,
122     CSSPropertyBorderBottomLeftRadius,
123     CSSPropertyBorderBottomRightRadius,
124     CSSPropertyBorderBottomStyle,
125     CSSPropertyBorderBottomWidth,
126     CSSPropertyBorderCollapse,
127     CSSPropertyBorderImageOutset,
128     CSSPropertyBorderImageRepeat,
129     CSSPropertyBorderImageSlice,
130     CSSPropertyBorderImageSource,
131     CSSPropertyBorderImageWidth,
132     CSSPropertyBorderLeftColor,
133     CSSPropertyBorderLeftStyle,
134     CSSPropertyBorderLeftWidth,
135     CSSPropertyBorderRightColor,
136     CSSPropertyBorderRightStyle,
137     CSSPropertyBorderRightWidth,
138     CSSPropertyBorderTopColor,
139     CSSPropertyBorderTopLeftRadius,
140     CSSPropertyBorderTopRightRadius,
141     CSSPropertyBorderTopStyle,
142     CSSPropertyBorderTopWidth,
143     CSSPropertyBottom,
144     CSSPropertyBoxShadow,
145     CSSPropertyBoxSizing,
146     CSSPropertyCaptionSide,
147     CSSPropertyClear,
148     CSSPropertyClip,
149     CSSPropertyColor,
150     CSSPropertyCounterIncrement,
151     CSSPropertyCounterReset,
152     CSSPropertyContent,
153     CSSPropertyCursor,
154     CSSPropertyDirection,
155     CSSPropertyDisplay,
156     CSSPropertyEmptyCells,
157     CSSPropertyFloat,
158     CSSPropertyFontFamily,
159     CSSPropertyFontSize,
160     CSSPropertyFontStretch,
161     CSSPropertyFontStyle,
162     CSSPropertyFontSynthesis,
163     CSSPropertyFontVariant,
164     CSSPropertyFontWeight,
165 #if ENABLE(VARIATION_FONTS)
166     CSSPropertyFontOpticalSizing,
167 #endif
168     CSSPropertyHangingPunctuation,
169     CSSPropertyHeight,
170 #if ENABLE(CSS_IMAGE_ORIENTATION)
171     CSSPropertyImageOrientation,
172 #endif
173     CSSPropertyImageRendering,
174 #if ENABLE(CSS_IMAGE_RESOLUTION)
175     CSSPropertyImageResolution,
176 #endif
177     CSSPropertyLeft,
178     CSSPropertyLetterSpacing,
179     CSSPropertyLineHeight,
180     CSSPropertyListStyleImage,
181     CSSPropertyListStylePosition,
182     CSSPropertyListStyleType,
183     CSSPropertyMarginBottom,
184     CSSPropertyMarginLeft,
185     CSSPropertyMarginRight,
186     CSSPropertyMarginTop,
187     CSSPropertyMaxHeight,
188     CSSPropertyMaxWidth,
189     CSSPropertyMinHeight,
190     CSSPropertyMinWidth,
191     CSSPropertyObjectFit,
192     CSSPropertyObjectPosition,
193     CSSPropertyOpacity,
194     CSSPropertyOrphans,
195     CSSPropertyOutlineColor,
196     CSSPropertyOutlineOffset,
197     CSSPropertyOutlineStyle,
198     CSSPropertyOutlineWidth,
199     CSSPropertyOverflowWrap,
200     CSSPropertyOverflowX,
201     CSSPropertyOverflowY,
202     CSSPropertyPaddingBottom,
203     CSSPropertyPaddingLeft,
204     CSSPropertyPaddingRight,
205     CSSPropertyPaddingTop,
206     CSSPropertyPageBreakAfter,
207     CSSPropertyPageBreakBefore,
208     CSSPropertyPageBreakInside,
209     CSSPropertyPointerEvents,
210     CSSPropertyPosition,
211     CSSPropertyResize,
212     CSSPropertyRight,
213     CSSPropertySpeak,
214     CSSPropertyTableLayout,
215     CSSPropertyTabSize,
216     CSSPropertyTextAlign,
217     CSSPropertyTextDecoration,
218 #if ENABLE(CSS3_TEXT)
219     CSSPropertyWebkitTextAlignLast,
220     CSSPropertyWebkitTextJustify,
221 #endif // CSS3_TEXT
222     CSSPropertyWebkitTextDecorationLine,
223     CSSPropertyWebkitTextDecorationStyle,
224     CSSPropertyWebkitTextDecorationColor,
225     CSSPropertyWebkitTextDecorationSkip,
226     CSSPropertyWebkitTextUnderlinePosition,
227     CSSPropertyTextIndent,
228     CSSPropertyTextRendering,
229     CSSPropertyTextShadow,
230     CSSPropertyTextOverflow,
231     CSSPropertyTextTransform,
232     CSSPropertyTop,
233     CSSPropertyTransform,
234     CSSPropertyTransformOrigin,
235     CSSPropertyTransformStyle,
236     CSSPropertyTransitionDelay,
237     CSSPropertyTransitionDuration,
238     CSSPropertyTransitionProperty,
239     CSSPropertyTransitionTimingFunction,
240     CSSPropertyUnicodeBidi,
241     CSSPropertyVerticalAlign,
242     CSSPropertyVisibility,
243     CSSPropertyWhiteSpace,
244     CSSPropertyWidows,
245     CSSPropertyWidth,
246     CSSPropertyWillChange,
247     CSSPropertyWordBreak,
248     CSSPropertyWordSpacing,
249     CSSPropertyWordWrap,
250 #if ENABLE(CSS_SCROLL_SNAP)
251     CSSPropertyScrollSnapMargin,
252     CSSPropertyScrollSnapMarginLeft,
253     CSSPropertyScrollSnapMarginTop,
254     CSSPropertyScrollSnapMarginRight,
255     CSSPropertyScrollSnapMarginBottom,
256     CSSPropertyScrollPadding,
257     CSSPropertyScrollPaddingLeft,
258     CSSPropertyScrollPaddingTop,
259     CSSPropertyScrollPaddingRight,
260     CSSPropertyScrollPaddingBottom,
261     CSSPropertyScrollSnapType,
262     CSSPropertyScrollSnapAlign,
263 #endif
264     CSSPropertyZIndex,
265     CSSPropertyZoom,
266 #if ENABLE(CSS_ANIMATIONS_LEVEL_2)
267     CSSPropertyWebkitAnimationTrigger,
268 #endif
269     CSSPropertyWebkitAppearance,
270     CSSPropertyWebkitBackfaceVisibility,
271     CSSPropertyWebkitBackgroundClip,
272     CSSPropertyWebkitBackgroundComposite,
273     CSSPropertyWebkitBackgroundOrigin,
274     CSSPropertyWebkitBackgroundSize,
275 #if ENABLE(CSS_COMPOSITING)
276     CSSPropertyMixBlendMode,
277     CSSPropertyIsolation,
278 #endif
279     CSSPropertyWebkitBorderFit,
280     CSSPropertyWebkitBorderHorizontalSpacing,
281     CSSPropertyWebkitBorderImage,
282     CSSPropertyWebkitBorderVerticalSpacing,
283     CSSPropertyWebkitBoxAlign,
284 #if ENABLE(CSS_BOX_DECORATION_BREAK)
285     CSSPropertyWebkitBoxDecorationBreak,
286 #endif
287     CSSPropertyWebkitBoxDirection,
288     CSSPropertyWebkitBoxFlex,
289     CSSPropertyWebkitBoxFlexGroup,
290     CSSPropertyWebkitBoxLines,
291     CSSPropertyWebkitBoxOrdinalGroup,
292     CSSPropertyWebkitBoxOrient,
293     CSSPropertyWebkitBoxPack,
294     CSSPropertyWebkitBoxReflect,
295     CSSPropertyWebkitBoxShadow,
296     CSSPropertyWebkitClipPath,
297     CSSPropertyWebkitColumnBreakAfter,
298     CSSPropertyWebkitColumnBreakBefore,
299     CSSPropertyWebkitColumnBreakInside,
300     CSSPropertyWebkitColumnAxis,
301     CSSPropertyColumnCount,
302     CSSPropertyColumnFill,
303     CSSPropertyColumnGap,
304     CSSPropertyWebkitColumnProgression,
305     CSSPropertyColumnRuleColor,
306     CSSPropertyColumnRuleStyle,
307     CSSPropertyColumnRuleWidth,
308     CSSPropertyColumnSpan,
309     CSSPropertyColumnWidth,
310 #if ENABLE(CURSOR_VISIBILITY)
311     CSSPropertyWebkitCursorVisibility,
312 #endif
313 #if ENABLE(DASHBOARD_SUPPORT)
314     CSSPropertyWebkitDashboardRegion,
315 #endif
316     CSSPropertyAlignContent,
317     CSSPropertyAlignItems,
318     CSSPropertyAlignSelf,
319     CSSPropertyFilter,
320     CSSPropertyFlexBasis,
321     CSSPropertyFlexDirection,
322     CSSPropertyFlexFlow,
323     CSSPropertyFlexGrow,
324     CSSPropertyFlexShrink,
325     CSSPropertyFlexWrap,
326     CSSPropertyJustifyContent,
327     CSSPropertyJustifySelf,
328     CSSPropertyJustifyItems,
329     CSSPropertyPlaceContent,
330     CSSPropertyPlaceItems,
331 #if ENABLE(FILTERS_LEVEL_2)
332     CSSPropertyWebkitBackdropFilter,
333 #endif
334     CSSPropertyWebkitFontKerning,
335     CSSPropertyWebkitFontSmoothing,
336     CSSPropertyFontVariantLigatures,
337     CSSPropertyFontVariantPosition,
338     CSSPropertyFontVariantCaps,
339     CSSPropertyFontVariantNumeric,
340     CSSPropertyFontVariantAlternates,
341     CSSPropertyFontVariantEastAsian,
342 #if ENABLE(VARIATION_FONTS)
343     CSSPropertyFontVariationSettings,
344 #endif
345     CSSPropertyGridAutoColumns,
346     CSSPropertyGridAutoFlow,
347     CSSPropertyGridAutoRows,
348     CSSPropertyGridColumnEnd,
349     CSSPropertyGridColumnStart,
350     CSSPropertyGridTemplateAreas,
351     CSSPropertyGridTemplateColumns,
352     CSSPropertyGridTemplateRows,
353     CSSPropertyGridRowEnd,
354     CSSPropertyGridRowStart,
355     CSSPropertyGridColumnGap,
356     CSSPropertyGridRowGap,
357     CSSPropertyWebkitHyphenateCharacter,
358     CSSPropertyWebkitHyphenateLimitAfter,
359     CSSPropertyWebkitHyphenateLimitBefore,
360     CSSPropertyWebkitHyphenateLimitLines,
361     CSSPropertyWebkitHyphens,
362     CSSPropertyWebkitInitialLetter,
363     CSSPropertyWebkitLineAlign,
364     CSSPropertyWebkitLineBoxContain,
365     CSSPropertyLineBreak,
366     CSSPropertyWebkitLineClamp,
367     CSSPropertyWebkitLineGrid,
368     CSSPropertyWebkitLineSnap,
369     CSSPropertyWebkitLocale,
370     CSSPropertyWebkitMarginBeforeCollapse,
371     CSSPropertyWebkitMarginAfterCollapse,
372     CSSPropertyWebkitMarqueeDirection,
373     CSSPropertyWebkitMarqueeIncrement,
374     CSSPropertyWebkitMarqueeRepetition,
375     CSSPropertyWebkitMarqueeStyle,
376     CSSPropertyWebkitMaskBoxImage,
377     CSSPropertyWebkitMaskBoxImageOutset,
378     CSSPropertyWebkitMaskBoxImageRepeat,
379     CSSPropertyWebkitMaskBoxImageSlice,
380     CSSPropertyWebkitMaskBoxImageSource,
381     CSSPropertyWebkitMaskBoxImageWidth,
382     CSSPropertyWebkitMaskClip,
383     CSSPropertyWebkitMaskComposite,
384     CSSPropertyWebkitMaskImage,
385     CSSPropertyWebkitMaskOrigin,
386     CSSPropertyWebkitMaskPosition,
387     CSSPropertyWebkitMaskRepeat,
388     CSSPropertyWebkitMaskSize,
389     CSSPropertyWebkitMaskSourceType,
390     CSSPropertyWebkitNbspMode,
391     CSSPropertyOrder,
392 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
393     CSSPropertyWebkitOverflowScrolling,
394 #endif
395     CSSPropertyPerspective,
396     CSSPropertyPerspectiveOrigin,
397     CSSPropertyWebkitPrintColorAdjust,
398     CSSPropertyWebkitRtlOrdering,
399 #if PLATFORM(IOS)
400     CSSPropertyWebkitTouchCallout,
401 #endif
402     CSSPropertyShapeOutside,
403 #if ENABLE(TOUCH_EVENTS)
404     CSSPropertyWebkitTapHighlightColor,
405 #endif
406     CSSPropertyWebkitTextCombine,
407     CSSPropertyWebkitTextDecorationsInEffect,
408     CSSPropertyWebkitTextEmphasisColor,
409     CSSPropertyWebkitTextEmphasisPosition,
410     CSSPropertyWebkitTextEmphasisStyle,
411     CSSPropertyWebkitTextFillColor,
412     CSSPropertyWebkitTextOrientation,
413     CSSPropertyWebkitTextSecurity,
414 #if ENABLE(TEXT_AUTOSIZING)
415     CSSPropertyWebkitTextSizeAdjust,
416 #endif
417     CSSPropertyWebkitTextStrokeColor,
418     CSSPropertyWebkitTextStrokeWidth,
419     CSSPropertyWebkitTextZoom,
420     CSSPropertyWebkitTransformStyle,
421     CSSPropertyWebkitUserDrag,
422     CSSPropertyWebkitUserModify,
423     CSSPropertyWebkitUserSelect,
424 #if ENABLE(CSS_REGIONS)
425     CSSPropertyWebkitFlowInto,
426     CSSPropertyWebkitFlowFrom,
427     CSSPropertyWebkitRegionBreakAfter,
428     CSSPropertyWebkitRegionBreakBefore,
429     CSSPropertyWebkitRegionBreakInside,
430     CSSPropertyWebkitRegionFragment,
431 #endif
432     CSSPropertyShapeImageThreshold,
433     CSSPropertyShapeMargin,
434     CSSPropertyShapeOutside,
435     CSSPropertyShapeRendering,
436     CSSPropertyBufferedRendering,
437     CSSPropertyClipPath,
438     CSSPropertyClipRule,
439     CSSPropertyCx,
440     CSSPropertyCy,
441     CSSPropertyMask,
442     CSSPropertyMaskType,
443     CSSPropertyFilter,
444     CSSPropertyFloodColor,
445     CSSPropertyFloodOpacity,
446     CSSPropertyLightingColor,
447     CSSPropertyStopColor,
448     CSSPropertyStopOpacity,
449     CSSPropertyColorInterpolation,
450     CSSPropertyColorInterpolationFilters,
451     CSSPropertyColorRendering,
452     CSSPropertyFill,
453     CSSPropertyFillOpacity,
454     CSSPropertyFillRule,
455     CSSPropertyMarkerEnd,
456     CSSPropertyMarkerMid,
457     CSSPropertyMarkerStart,
458     CSSPropertyPaintOrder,
459     CSSPropertyR,
460     CSSPropertyRx,
461     CSSPropertyRy,
462     CSSPropertyStroke,
463     CSSPropertyStrokeColor,
464     CSSPropertyStrokeDasharray,
465     CSSPropertyStrokeDashoffset,
466     CSSPropertyStrokeLinecap,
467     CSSPropertyStrokeLinejoin,
468     CSSPropertyStrokeMiterlimit,
469     CSSPropertyStrokeOpacity,
470     CSSPropertyStrokeWidth,
471     CSSPropertyAlignmentBaseline,
472     CSSPropertyBaselineShift,
473     CSSPropertyDominantBaseline,
474     CSSPropertyKerning,
475     CSSPropertyTextAnchor,
476     CSSPropertyWritingMode,
477     CSSPropertyGlyphOrientationHorizontal,
478     CSSPropertyGlyphOrientationVertical,
479     CSSPropertyWebkitSvgShadow,
480     CSSPropertyVectorEffect,
481     CSSPropertyX,
482     CSSPropertyY
483 };
484
485 const unsigned numComputedProperties = WTF_ARRAY_LENGTH(computedProperties);
486
487 static CSSValueID valueForRepeatRule(int rule)
488 {
489     switch (rule) {
490         case RepeatImageRule:
491             return CSSValueRepeat;
492         case RoundImageRule:
493             return CSSValueRound;
494         case SpaceImageRule:
495             return CSSValueSpace;
496         default:
497             return CSSValueStretch;
498     }
499 }
500
501 static Ref<CSSPrimitiveValue> valueForImageSliceSide(const Length& length)
502 {
503     // These values can be percentages, numbers, or while an animation of mixed types is in progress,
504     // a calculation that combines a percentage and a number.
505     if (length.isPercent())
506         return CSSValuePool::singleton().createValue(length.percent(), CSSPrimitiveValue::CSS_PERCENTAGE);
507     if (length.isFixed())
508         return CSSValuePool::singleton().createValue(length.value(), CSSPrimitiveValue::CSS_NUMBER);
509
510     // Calculating the actual length currently in use would require most of the code from RenderBoxModelObject::paintNinePieceImage.
511     // And even if we could do that, it's not clear if that's exactly what we'd want during animation.
512     // FIXME: For now, just return 0.
513     ASSERT(length.isCalculated());
514     return CSSValuePool::singleton().createValue(0, CSSPrimitiveValue::CSS_NUMBER);
515 }
516
517 static Ref<CSSBorderImageSliceValue> valueForNinePieceImageSlice(const NinePieceImage& image)
518 {
519     auto& slices = image.imageSlices();
520
521     RefPtr<CSSPrimitiveValue> top = valueForImageSliceSide(slices.top());
522
523     RefPtr<CSSPrimitiveValue> right;
524     RefPtr<CSSPrimitiveValue> bottom;
525     RefPtr<CSSPrimitiveValue> left;
526
527     if (slices.right() == slices.top() && slices.bottom() == slices.top() && slices.left() == slices.top()) {
528         right = top;
529         bottom = top;
530         left = top;
531     } else {
532         right = valueForImageSliceSide(slices.right());
533
534         if (slices.bottom() == slices.top() && slices.right() == slices.left()) {
535             bottom = top;
536             left = right;
537         } else {
538             bottom = valueForImageSliceSide(slices.bottom());
539
540             if (slices.left() == slices.right())
541                 left = right;
542             else
543                 left = valueForImageSliceSide(slices.left());
544         }
545     }
546
547     auto quad = Quad::create();
548     quad->setTop(WTFMove(top));
549     quad->setRight(WTFMove(right));
550     quad->setBottom(WTFMove(bottom));
551     quad->setLeft(WTFMove(left));
552
553     return CSSBorderImageSliceValue::create(CSSValuePool::singleton().createValue(WTFMove(quad)), image.fill());
554 }
555
556 static Ref<CSSPrimitiveValue> valueForNinePieceImageQuad(const LengthBox& box)
557 {
558     RefPtr<CSSPrimitiveValue> top;
559     RefPtr<CSSPrimitiveValue> right;
560     RefPtr<CSSPrimitiveValue> bottom;
561     RefPtr<CSSPrimitiveValue> left;
562
563     auto& cssValuePool = CSSValuePool::singleton();
564
565     if (box.top().isRelative())
566         top = cssValuePool.createValue(box.top().value(), CSSPrimitiveValue::CSS_NUMBER);
567     else
568         top = cssValuePool.createValue(box.top());
569
570     if (box.right() == box.top() && box.bottom() == box.top() && box.left() == box.top()) {
571         right = top;
572         bottom = top;
573         left = top;
574     } else {
575         if (box.right().isRelative())
576             right = cssValuePool.createValue(box.right().value(), CSSPrimitiveValue::CSS_NUMBER);
577         else
578             right = cssValuePool.createValue(box.right());
579
580         if (box.bottom() == box.top() && box.right() == box.left()) {
581             bottom = top;
582             left = right;
583         } else {
584             if (box.bottom().isRelative())
585                 bottom = cssValuePool.createValue(box.bottom().value(), CSSPrimitiveValue::CSS_NUMBER);
586             else
587                 bottom = cssValuePool.createValue(box.bottom());
588
589             if (box.left() == box.right())
590                 left = right;
591             else {
592                 if (box.left().isRelative())
593                     left = cssValuePool.createValue(box.left().value(), CSSPrimitiveValue::CSS_NUMBER);
594                 else
595                     left = cssValuePool.createValue(box.left());
596             }
597         }
598     }
599
600     auto quad = Quad::create();
601     quad->setTop(WTFMove(top));
602     quad->setRight(WTFMove(right));
603     quad->setBottom(WTFMove(bottom));
604     quad->setLeft(WTFMove(left));
605
606     return cssValuePool.createValue(WTFMove(quad));
607 }
608
609 static Ref<CSSValue> valueForNinePieceImageRepeat(const NinePieceImage& image)
610 {
611     auto& cssValuePool = CSSValuePool::singleton();
612     auto horizontalRepeat = cssValuePool.createIdentifierValue(valueForRepeatRule(image.horizontalRule()));
613     RefPtr<CSSPrimitiveValue> verticalRepeat;
614     if (image.horizontalRule() == image.verticalRule())
615         verticalRepeat = horizontalRepeat.copyRef();
616     else
617         verticalRepeat = cssValuePool.createIdentifierValue(valueForRepeatRule(image.verticalRule()));
618     return cssValuePool.createValue(Pair::create(WTFMove(horizontalRepeat), WTFMove(verticalRepeat)));
619 }
620
621 static Ref<CSSValue> valueForNinePieceImage(const NinePieceImage& image)
622 {
623     if (!image.hasImage())
624         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
625
626     // Image first.
627     RefPtr<CSSValue> imageValue;
628     if (image.image())
629         imageValue = image.image()->cssValue();
630
631     // Create the image slice.
632     RefPtr<CSSBorderImageSliceValue> imageSlices = valueForNinePieceImageSlice(image);
633
634     // Create the border area slices.
635     RefPtr<CSSValue> borderSlices = valueForNinePieceImageQuad(image.borderSlices());
636
637     // Create the border outset.
638     RefPtr<CSSValue> outset = valueForNinePieceImageQuad(image.outset());
639
640     // Create the repeat rules.
641     RefPtr<CSSValue> repeat = valueForNinePieceImageRepeat(image);
642
643     return createBorderImageValue(WTFMove(imageValue), WTFMove(imageSlices), WTFMove(borderSlices), WTFMove(outset), WTFMove(repeat));
644 }
645
646 inline static Ref<CSSPrimitiveValue> zoomAdjustedPixelValue(double value, const RenderStyle& style)
647 {
648     return CSSValuePool::singleton().createValue(adjustFloatForAbsoluteZoom(value, style), CSSPrimitiveValue::CSS_PX);
649 }
650
651 inline static Ref<CSSPrimitiveValue> zoomAdjustedNumberValue(double value, const RenderStyle& style)
652 {
653     return CSSValuePool::singleton().createValue(value / style.effectiveZoom(), CSSPrimitiveValue::CSS_NUMBER);
654 }
655
656 static Ref<CSSValue> zoomAdjustedPixelValueForLength(const Length& length, const RenderStyle& style)
657 {
658     if (length.isFixed())
659         return zoomAdjustedPixelValue(length.value(), style);
660     return CSSValuePool::singleton().createValue(length, style);
661 }
662
663 static Ref<CSSValue> valueForReflection(const StyleReflection* reflection, const RenderStyle& style)
664 {
665     if (!reflection)
666         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
667
668     RefPtr<CSSPrimitiveValue> offset;
669     if (reflection->offset().isPercentOrCalculated())
670         offset = CSSValuePool::singleton().createValue(reflection->offset().percent(), CSSPrimitiveValue::CSS_PERCENTAGE);
671     else
672         offset = zoomAdjustedPixelValue(reflection->offset().value(), style);
673
674     RefPtr<CSSPrimitiveValue> direction;
675     switch (reflection->direction()) {
676     case ReflectionBelow:
677         direction = CSSValuePool::singleton().createIdentifierValue(CSSValueBelow);
678         break;
679     case ReflectionAbove:
680         direction = CSSValuePool::singleton().createIdentifierValue(CSSValueAbove);
681         break;
682     case ReflectionLeft:
683         direction = CSSValuePool::singleton().createIdentifierValue(CSSValueLeft);
684         break;
685     case ReflectionRight:
686         direction = CSSValuePool::singleton().createIdentifierValue(CSSValueRight);
687         break;
688     }
689
690     return CSSReflectValue::create(direction.releaseNonNull(), offset.releaseNonNull(), valueForNinePieceImage(reflection->mask()));
691 }
692
693 static Ref<CSSValueList> createPositionListForLayer(CSSPropertyID propertyID, const FillLayer& layer, const RenderStyle& style)
694 {
695     auto list = CSSValueList::createSpaceSeparated();
696     if (layer.isBackgroundXOriginSet()) {
697         ASSERT_UNUSED(propertyID, propertyID == CSSPropertyBackgroundPosition || propertyID == CSSPropertyWebkitMaskPosition);
698         list->append(CSSValuePool::singleton().createValue(layer.backgroundXOrigin()));
699     }
700     list->append(zoomAdjustedPixelValueForLength(layer.xPosition(), style));
701     if (layer.isBackgroundYOriginSet()) {
702         ASSERT(propertyID == CSSPropertyBackgroundPosition || propertyID == CSSPropertyWebkitMaskPosition);
703         list->append(CSSValuePool::singleton().createValue(layer.backgroundYOrigin()));
704     }
705     list->append(zoomAdjustedPixelValueForLength(layer.yPosition(), style));
706     return list;
707 }
708
709 static RefPtr<CSSValue> positionOffsetValue(const RenderStyle& style, CSSPropertyID propertyID)
710 {
711     Length length;
712     switch (propertyID) {
713         case CSSPropertyLeft:
714             length = style.left();
715             break;
716         case CSSPropertyRight:
717             length = style.right();
718             break;
719         case CSSPropertyTop:
720             length = style.top();
721             break;
722         case CSSPropertyBottom:
723             length = style.bottom();
724             break;
725         default:
726             return nullptr;
727     }
728
729     if (style.hasOutOfFlowPosition()) {
730         if (length.isFixed())
731             return zoomAdjustedPixelValue(length.value(), style);
732
733         return CSSValuePool::singleton().createValue(length);
734     }
735
736     if (style.hasInFlowPosition()) {
737         // FIXME: It's not enough to simply return "auto" values for one offset if the other side is defined.
738         // In other words if left is auto and right is not auto, then left's computed value is negative right().
739         // So we should get the opposite length unit and see if it is auto.
740         return CSSValuePool::singleton().createValue(length);
741     }
742
743     return CSSValuePool::singleton().createIdentifierValue(CSSValueAuto);
744 }
745
746 RefPtr<CSSPrimitiveValue> ComputedStyleExtractor::currentColorOrValidColor(const RenderStyle* style, const Color& color) const
747 {
748     // This function does NOT look at visited information, so that computed style doesn't expose that.
749     if (!color.isValid())
750         return CSSValuePool::singleton().createColorValue(style->color());
751     return CSSValuePool::singleton().createColorValue(color);
752 }
753
754 static Ref<CSSPrimitiveValue> percentageOrZoomAdjustedValue(Length length, const RenderStyle& style)
755 {
756     if (length.isPercent())
757         return CSSValuePool::singleton().createValue(length.percent(), CSSPrimitiveValue::CSS_PERCENTAGE);
758     
759     return zoomAdjustedPixelValue(valueForLength(length, 0), style);
760 }
761
762 static Ref<CSSPrimitiveValue> autoOrZoomAdjustedValue(Length length, const RenderStyle& style)
763 {
764     if (length.isAuto())
765         return CSSValuePool::singleton().createIdentifierValue(CSSValueAuto);
766
767     return zoomAdjustedPixelValue(valueForLength(length, 0), style);
768 }
769
770 static Ref<CSSValueList> borderRadiusCornerValues(const LengthSize& radius, const RenderStyle& style)
771 {
772     auto list = CSSValueList::createSpaceSeparated();
773     list->append(percentageOrZoomAdjustedValue(radius.width, style));
774     list->append(percentageOrZoomAdjustedValue(radius.height, style));
775     return list;
776 }
777
778 static Ref<CSSValue> borderRadiusCornerValue(const LengthSize& radius, const RenderStyle& style)
779 {
780     if (radius.width == radius.height)
781         return percentageOrZoomAdjustedValue(radius.width, style);
782     return borderRadiusCornerValues(radius, style);
783 }
784
785 static Ref<CSSValueList> borderRadiusShorthandValue(const RenderStyle& style)
786 {
787     auto list = CSSValueList::createSlashSeparated();
788     bool showHorizontalBottomLeft = style.borderTopRightRadius().width != style.borderBottomLeftRadius().width;
789     bool showHorizontalBottomRight = showHorizontalBottomLeft || (style.borderBottomRightRadius().width != style.borderTopLeftRadius().width);
790     bool showHorizontalTopRight = showHorizontalBottomRight || (style.borderTopRightRadius().width != style.borderTopLeftRadius().width);
791
792     bool showVerticalBottomLeft = style.borderTopRightRadius().height != style.borderBottomLeftRadius().height;
793     bool showVerticalBottomRight = showVerticalBottomLeft || (style.borderBottomRightRadius().height != style.borderTopLeftRadius().height);
794     bool showVerticalTopRight = showVerticalBottomRight || (style.borderTopRightRadius().height != style.borderTopLeftRadius().height);
795
796     auto topLeftRadius = borderRadiusCornerValues(style.borderTopLeftRadius(), style);
797     auto topRightRadius = borderRadiusCornerValues(style.borderTopRightRadius(), style);
798     auto bottomRightRadius = borderRadiusCornerValues(style.borderBottomRightRadius(), style);
799     auto bottomLeftRadius = borderRadiusCornerValues(style.borderBottomLeftRadius(), style);
800
801     auto horizontalRadii = CSSValueList::createSpaceSeparated();
802     horizontalRadii->append(*topLeftRadius->item(0));
803     if (showHorizontalTopRight)
804         horizontalRadii->append(*topRightRadius->item(0));
805     if (showHorizontalBottomRight)
806         horizontalRadii->append(*bottomRightRadius->item(0));
807     if (showHorizontalBottomLeft)
808         horizontalRadii->append(*bottomLeftRadius->item(0));
809
810     list->append(WTFMove(horizontalRadii));
811
812     auto verticalRadiiList = CSSValueList::createSpaceSeparated();
813     verticalRadiiList->append(*topLeftRadius->item(1));
814     if (showVerticalTopRight)
815         verticalRadiiList->append(*topRightRadius->item(1));
816     if (showVerticalBottomRight)
817         verticalRadiiList->append(*bottomRightRadius->item(1));
818     if (showVerticalBottomLeft)
819         verticalRadiiList->append(*bottomLeftRadius->item(1));
820
821     if (!verticalRadiiList->equals(downcast<CSSValueList>(*list->item(0))))
822         list->append(WTFMove(verticalRadiiList));
823
824     return list;
825 }
826
827 static LayoutRect sizingBox(RenderObject& renderer)
828 {
829     if (!is<RenderBox>(renderer))
830         return LayoutRect();
831
832     auto& box = downcast<RenderBox>(renderer);
833     return box.style().boxSizing() == BORDER_BOX ? box.borderBoxRect() : box.computedCSSContentBoxRect();
834 }
835
836 static Ref<CSSFunctionValue> matrixTransformValue(const TransformationMatrix& transform, const RenderStyle& style)
837 {
838     RefPtr<CSSFunctionValue> transformValue;
839     auto& cssValuePool = CSSValuePool::singleton();
840     if (transform.isAffine()) {
841         transformValue = CSSFunctionValue::create(CSSValueMatrix);
842
843         transformValue->append(cssValuePool.createValue(transform.a(), CSSPrimitiveValue::CSS_NUMBER));
844         transformValue->append(cssValuePool.createValue(transform.b(), CSSPrimitiveValue::CSS_NUMBER));
845         transformValue->append(cssValuePool.createValue(transform.c(), CSSPrimitiveValue::CSS_NUMBER));
846         transformValue->append(cssValuePool.createValue(transform.d(), CSSPrimitiveValue::CSS_NUMBER));
847         transformValue->append(zoomAdjustedNumberValue(transform.e(), style));
848         transformValue->append(zoomAdjustedNumberValue(transform.f(), style));
849     } else {
850         transformValue = CSSFunctionValue::create(CSSValueMatrix3d);
851
852         transformValue->append(cssValuePool.createValue(transform.m11(), CSSPrimitiveValue::CSS_NUMBER));
853         transformValue->append(cssValuePool.createValue(transform.m12(), CSSPrimitiveValue::CSS_NUMBER));
854         transformValue->append(cssValuePool.createValue(transform.m13(), CSSPrimitiveValue::CSS_NUMBER));
855         transformValue->append(cssValuePool.createValue(transform.m14(), CSSPrimitiveValue::CSS_NUMBER));
856
857         transformValue->append(cssValuePool.createValue(transform.m21(), CSSPrimitiveValue::CSS_NUMBER));
858         transformValue->append(cssValuePool.createValue(transform.m22(), CSSPrimitiveValue::CSS_NUMBER));
859         transformValue->append(cssValuePool.createValue(transform.m23(), CSSPrimitiveValue::CSS_NUMBER));
860         transformValue->append(cssValuePool.createValue(transform.m24(), CSSPrimitiveValue::CSS_NUMBER));
861
862         transformValue->append(cssValuePool.createValue(transform.m31(), CSSPrimitiveValue::CSS_NUMBER));
863         transformValue->append(cssValuePool.createValue(transform.m32(), CSSPrimitiveValue::CSS_NUMBER));
864         transformValue->append(cssValuePool.createValue(transform.m33(), CSSPrimitiveValue::CSS_NUMBER));
865         transformValue->append(cssValuePool.createValue(transform.m34(), CSSPrimitiveValue::CSS_NUMBER));
866
867         transformValue->append(zoomAdjustedNumberValue(transform.m41(), style));
868         transformValue->append(zoomAdjustedNumberValue(transform.m42(), style));
869         transformValue->append(zoomAdjustedNumberValue(transform.m43(), style));
870         transformValue->append(cssValuePool.createValue(transform.m44(), CSSPrimitiveValue::CSS_NUMBER));
871     }
872
873     return transformValue.releaseNonNull();
874 }
875
876 static Ref<CSSValue> computedTransform(RenderObject* renderer, const RenderStyle& style)
877 {
878     if (!renderer || !renderer->hasTransform())
879         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
880
881     FloatRect pixelSnappedRect;
882     if (is<RenderBox>(*renderer))
883         pixelSnappedRect = snapRectToDevicePixels(downcast<RenderBox>(*renderer).borderBoxRect(), renderer->document().deviceScaleFactor());
884
885     TransformationMatrix transform;
886     style.applyTransform(transform, pixelSnappedRect, RenderStyle::ExcludeTransformOrigin);
887     // Note that this does not flatten to an affine transform if ENABLE(3D_TRANSFORMS) is off, by design.
888
889     // FIXME: Need to print out individual functions (https://bugs.webkit.org/show_bug.cgi?id=23924)
890     auto list = CSSValueList::createSpaceSeparated();
891     list->append(matrixTransformValue(transform, style));
892     return WTFMove(list);
893 }
894
895 static inline Ref<CSSPrimitiveValue> adjustLengthForZoom(double length, const RenderStyle& style, AdjustPixelValuesForComputedStyle adjust)
896 {
897     return adjust == AdjustPixelValues ? zoomAdjustedPixelValue(length, style) : CSSValuePool::singleton().createValue(length, CSSPrimitiveValue::CSS_PX);
898 }
899
900 static inline Ref<CSSPrimitiveValue> adjustLengthForZoom(const Length& length, const RenderStyle& style, AdjustPixelValuesForComputedStyle adjust)
901 {
902     return adjust == AdjustPixelValues ? zoomAdjustedPixelValue(length.value(), style) : CSSValuePool::singleton().createValue(length);
903 }
904
905 Ref<CSSValue> ComputedStyleExtractor::valueForShadow(const ShadowData* shadow, CSSPropertyID propertyID, const RenderStyle& style, AdjustPixelValuesForComputedStyle adjust)
906 {
907     auto& cssValuePool = CSSValuePool::singleton();
908     if (!shadow)
909         return cssValuePool.createIdentifierValue(CSSValueNone);
910
911     auto list = CSSValueList::createCommaSeparated();
912     for (const ShadowData* currShadowData = shadow; currShadowData; currShadowData = currShadowData->next()) {
913         auto x = adjustLengthForZoom(currShadowData->x(), style, adjust);
914         auto y = adjustLengthForZoom(currShadowData->y(), style, adjust);
915         auto blur = adjustLengthForZoom(currShadowData->radius(), style, adjust);
916         auto spread = propertyID == CSSPropertyTextShadow ? RefPtr<CSSPrimitiveValue>() : adjustLengthForZoom(currShadowData->spread(), style, adjust);
917         auto style = propertyID == CSSPropertyTextShadow || currShadowData->style() == Normal ? RefPtr<CSSPrimitiveValue>() : cssValuePool.createIdentifierValue(CSSValueInset);
918         auto color = cssValuePool.createColorValue(currShadowData->color());
919         list->prepend(CSSShadowValue::create(WTFMove(x), WTFMove(y), WTFMove(blur), WTFMove(spread), WTFMove(style), WTFMove(color)));
920     }
921     return WTFMove(list);
922 }
923
924 Ref<CSSValue> ComputedStyleExtractor::valueForFilter(const RenderStyle& style, const FilterOperations& filterOperations, AdjustPixelValuesForComputedStyle adjust)
925 {
926     auto& cssValuePool = CSSValuePool::singleton();
927     if (filterOperations.operations().isEmpty())
928         return cssValuePool.createIdentifierValue(CSSValueNone);
929
930     auto list = CSSValueList::createSpaceSeparated();
931
932     Vector<RefPtr<FilterOperation>>::const_iterator end = filterOperations.operations().end();
933     for (Vector<RefPtr<FilterOperation>>::const_iterator it = filterOperations.operations().begin(); it != end; ++it) {
934         FilterOperation& filterOperation = **it;
935
936         if (filterOperation.type() == FilterOperation::REFERENCE) {
937             ReferenceFilterOperation& referenceOperation = downcast<ReferenceFilterOperation>(filterOperation);
938             list->append(cssValuePool.createValue(referenceOperation.url(), CSSPrimitiveValue::CSS_URI));
939         } else {
940             RefPtr<CSSFunctionValue> filterValue;
941             switch (filterOperation.type()) {
942             case FilterOperation::GRAYSCALE: {
943                 filterValue = CSSFunctionValue::create(CSSValueGrayscale);
944                 filterValue->append(cssValuePool.createValue(downcast<BasicColorMatrixFilterOperation>(filterOperation).amount(), CSSPrimitiveValue::CSS_NUMBER));
945                 break;
946             }
947             case FilterOperation::SEPIA: {
948                 filterValue = CSSFunctionValue::create(CSSValueSepia);
949                 filterValue->append(cssValuePool.createValue(downcast<BasicColorMatrixFilterOperation>(filterOperation).amount(), CSSPrimitiveValue::CSS_NUMBER));
950                 break;
951             }
952             case FilterOperation::SATURATE: {
953                 filterValue = CSSFunctionValue::create(CSSValueSaturate);
954                 filterValue->append(cssValuePool.createValue(downcast<BasicColorMatrixFilterOperation>(filterOperation).amount(), CSSPrimitiveValue::CSS_NUMBER));
955                 break;
956             }
957             case FilterOperation::HUE_ROTATE: {
958                 filterValue = CSSFunctionValue::create(CSSValueHueRotate);
959                 filterValue->append(cssValuePool.createValue(downcast<BasicColorMatrixFilterOperation>(filterOperation).amount(), CSSPrimitiveValue::CSS_DEG));
960                 break;
961             }
962             case FilterOperation::INVERT: {
963                 filterValue = CSSFunctionValue::create(CSSValueInvert);
964                 filterValue->append(cssValuePool.createValue(downcast<BasicComponentTransferFilterOperation>(filterOperation).amount(), CSSPrimitiveValue::CSS_NUMBER));
965                 break;
966             }
967             case FilterOperation::OPACITY: {
968                 filterValue = CSSFunctionValue::create(CSSValueOpacity);
969                 filterValue->append(cssValuePool.createValue(downcast<BasicComponentTransferFilterOperation>(filterOperation).amount(), CSSPrimitiveValue::CSS_NUMBER));
970                 break;
971             }
972             case FilterOperation::BRIGHTNESS: {
973                 filterValue = CSSFunctionValue::create(CSSValueBrightness);
974                 filterValue->append(cssValuePool.createValue(downcast<BasicComponentTransferFilterOperation>(filterOperation).amount(), CSSPrimitiveValue::CSS_NUMBER));
975                 break;
976             }
977             case FilterOperation::CONTRAST: {
978                 filterValue = CSSFunctionValue::create(CSSValueContrast);
979                 filterValue->append(cssValuePool.createValue(downcast<BasicComponentTransferFilterOperation>(filterOperation).amount(), CSSPrimitiveValue::CSS_NUMBER));
980                 break;
981             }
982             case FilterOperation::BLUR: {
983                 filterValue = CSSFunctionValue::create(CSSValueBlur);
984                 filterValue->append(adjustLengthForZoom(downcast<BlurFilterOperation>(filterOperation).stdDeviation(), style, adjust));
985                 break;
986             }
987             case FilterOperation::DROP_SHADOW: {
988                 DropShadowFilterOperation& dropShadowOperation = downcast<DropShadowFilterOperation>(filterOperation);
989                 filterValue = CSSFunctionValue::create(CSSValueDropShadow);
990                 // We want our computed style to look like that of a text shadow (has neither spread nor inset style).
991                 ShadowData shadowData = ShadowData(dropShadowOperation.location(), dropShadowOperation.stdDeviation(), 0, Normal, false, dropShadowOperation.color());
992                 filterValue->append(valueForShadow(&shadowData, CSSPropertyTextShadow, style, adjust));
993                 break;
994             }
995             default:
996                 ASSERT_NOT_REACHED();
997                 filterValue = CSSFunctionValue::create(CSSValueInvalid);
998                 break;
999             }
1000             list->append(filterValue.releaseNonNull());
1001         }
1002     }
1003     return WTFMove(list);
1004 }
1005
1006 static Ref<CSSValue> specifiedValueForGridTrackBreadth(const GridLength& trackBreadth, const RenderStyle& style)
1007 {
1008     if (!trackBreadth.isLength())
1009         return CSSValuePool::singleton().createValue(trackBreadth.flex(), CSSPrimitiveValue::CSS_FR);
1010
1011     const Length& trackBreadthLength = trackBreadth.length();
1012     if (trackBreadthLength.isAuto())
1013         return CSSValuePool::singleton().createIdentifierValue(CSSValueAuto);
1014     return zoomAdjustedPixelValueForLength(trackBreadthLength, style);
1015 }
1016
1017 static Ref<CSSValue> specifiedValueForGridTrackSize(const GridTrackSize& trackSize, const RenderStyle& style)
1018 {
1019     switch (trackSize.type()) {
1020     case LengthTrackSizing:
1021         return specifiedValueForGridTrackBreadth(trackSize.minTrackBreadth(), style);
1022     case FitContentTrackSizing: {
1023         auto fitContentTrackSize = CSSFunctionValue::create(CSSValueFitContent);
1024         fitContentTrackSize->append(zoomAdjustedPixelValueForLength(trackSize.fitContentTrackBreadth().length(), style));
1025         return WTFMove(fitContentTrackSize);
1026     }
1027     default:
1028         ASSERT(trackSize.type() == MinMaxTrackSizing);
1029         if (trackSize.minTrackBreadth().isAuto() && trackSize.maxTrackBreadth().isFlex())
1030             return CSSValuePool::singleton().createValue(trackSize.maxTrackBreadth().flex(), CSSPrimitiveValue::CSS_FR);
1031
1032         auto minMaxTrackBreadths = CSSFunctionValue::create(CSSValueMinmax);
1033         minMaxTrackBreadths->append(specifiedValueForGridTrackBreadth(trackSize.minTrackBreadth(), style));
1034         minMaxTrackBreadths->append(specifiedValueForGridTrackBreadth(trackSize.maxTrackBreadth(), style));
1035         return WTFMove(minMaxTrackBreadths);
1036     }
1037 }
1038
1039 class OrderedNamedLinesCollector {
1040     WTF_MAKE_NONCOPYABLE(OrderedNamedLinesCollector);
1041 public:
1042     OrderedNamedLinesCollector(const RenderStyle& style, bool isRowAxis, unsigned autoRepeatTracksCount)
1043         : m_orderedNamedGridLines(isRowAxis ? style.orderedNamedGridColumnLines() : style.orderedNamedGridRowLines())
1044         , m_orderedNamedAutoRepeatGridLines(isRowAxis ? style.autoRepeatOrderedNamedGridColumnLines() : style.autoRepeatOrderedNamedGridRowLines())
1045         , m_insertionPoint(isRowAxis ? style.gridAutoRepeatColumnsInsertionPoint() : style.gridAutoRepeatRowsInsertionPoint())
1046         , m_autoRepeatTotalTracks(autoRepeatTracksCount)
1047         , m_autoRepeatTrackListLength(isRowAxis ? style.gridAutoRepeatColumns().size() : style.gridAutoRepeatRows().size())
1048     {
1049     }
1050
1051     bool isEmpty() const { return m_orderedNamedGridLines.isEmpty() && m_orderedNamedAutoRepeatGridLines.isEmpty(); }
1052     void collectLineNamesForIndex(CSSGridLineNamesValue&, unsigned index) const;
1053
1054 private:
1055
1056     enum NamedLinesType { NamedLines, AutoRepeatNamedLines };
1057     void appendLines(CSSGridLineNamesValue&, unsigned index, NamedLinesType) const;
1058
1059     const OrderedNamedGridLinesMap& m_orderedNamedGridLines;
1060     const OrderedNamedGridLinesMap& m_orderedNamedAutoRepeatGridLines;
1061     unsigned m_insertionPoint;
1062     unsigned m_autoRepeatTotalTracks;
1063     unsigned m_autoRepeatTrackListLength;
1064 };
1065
1066 void OrderedNamedLinesCollector::appendLines(CSSGridLineNamesValue& lineNamesValue, unsigned index, NamedLinesType type) const
1067 {
1068     auto iter = type == NamedLines ? m_orderedNamedGridLines.find(index) : m_orderedNamedAutoRepeatGridLines.find(index);
1069     auto endIter = type == NamedLines ? m_orderedNamedGridLines.end() : m_orderedNamedAutoRepeatGridLines.end();
1070     if (iter == endIter)
1071         return;
1072
1073     auto& cssValuePool = CSSValuePool::singleton();
1074     for (auto lineName : iter->value)
1075         lineNamesValue.append(cssValuePool.createValue(lineName, CSSPrimitiveValue::CSS_STRING));
1076 }
1077
1078 void OrderedNamedLinesCollector::collectLineNamesForIndex(CSSGridLineNamesValue& lineNamesValue, unsigned i) const
1079 {
1080     ASSERT(!isEmpty());
1081     if (m_orderedNamedAutoRepeatGridLines.isEmpty() || i < m_insertionPoint) {
1082         appendLines(lineNamesValue, i, NamedLines);
1083         return;
1084     }
1085
1086     ASSERT(m_autoRepeatTotalTracks);
1087
1088     if (i > m_insertionPoint + m_autoRepeatTotalTracks) {
1089         appendLines(lineNamesValue, i - (m_autoRepeatTotalTracks - 1), NamedLines);
1090         return;
1091     }
1092
1093     if (i == m_insertionPoint) {
1094         appendLines(lineNamesValue, i, NamedLines);
1095         appendLines(lineNamesValue, 0, AutoRepeatNamedLines);
1096         return;
1097     }
1098
1099     if (i == m_insertionPoint + m_autoRepeatTotalTracks) {
1100         appendLines(lineNamesValue, m_autoRepeatTrackListLength, AutoRepeatNamedLines);
1101         appendLines(lineNamesValue, m_insertionPoint + 1, NamedLines);
1102         return;
1103     }
1104
1105     unsigned autoRepeatIndexInFirstRepetition = (i - m_insertionPoint) % m_autoRepeatTrackListLength;
1106     if (!autoRepeatIndexInFirstRepetition && i > m_insertionPoint)
1107         appendLines(lineNamesValue, m_autoRepeatTrackListLength, AutoRepeatNamedLines);
1108     appendLines(lineNamesValue, autoRepeatIndexInFirstRepetition, AutoRepeatNamedLines);
1109 }
1110
1111 static void addValuesForNamedGridLinesAtIndex(OrderedNamedLinesCollector& collector, unsigned i, CSSValueList& list)
1112 {
1113     if (collector.isEmpty())
1114         return;
1115
1116     auto lineNames = CSSGridLineNamesValue::create();
1117     collector.collectLineNamesForIndex(lineNames.get(), i);
1118     if (lineNames->length())
1119         list.append(WTFMove(lineNames));
1120 }
1121
1122 static Ref<CSSValueList> valueForGridTrackSizeList(GridTrackSizingDirection direction, const RenderStyle& style)
1123 {
1124     auto& autoTrackSizes = direction == ForColumns ? style.gridAutoColumns() : style.gridAutoRows();
1125
1126     auto list = CSSValueList::createSpaceSeparated();
1127     for (auto& trackSize : autoTrackSizes)
1128         list->append(specifiedValueForGridTrackSize(trackSize, style));
1129     return list;
1130 }
1131
1132 static Ref<CSSValue> valueForGridTrackList(GridTrackSizingDirection direction, RenderObject* renderer, const RenderStyle& style)
1133 {
1134     bool isRowAxis = direction == ForColumns;
1135     bool isRenderGrid = is<RenderGrid>(renderer);
1136     auto& trackSizes = isRowAxis ? style.gridColumns() : style.gridRows();
1137     auto& autoRepeatTrackSizes = isRowAxis ? style.gridAutoRepeatColumns() : style.gridAutoRepeatRows();
1138
1139     // Handle the 'none' case.
1140     bool trackListIsEmpty = trackSizes.isEmpty() && autoRepeatTrackSizes.isEmpty();
1141     if (isRenderGrid && trackListIsEmpty) {
1142         // For grids we should consider every listed track, whether implicitly or explicitly
1143         // created. Empty grids have a sole grid line per axis.
1144         auto& grid = downcast<RenderGrid>(*renderer);
1145         auto& positions = isRowAxis ? grid.columnPositions() : grid.rowPositions();
1146         trackListIsEmpty = positions.size() == 1;
1147     }
1148
1149     if (trackListIsEmpty)
1150         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
1151
1152     unsigned autoRepeatTotalTracks = isRenderGrid ? downcast<RenderGrid>(renderer)->autoRepeatCountForDirection(direction) : 0;
1153     OrderedNamedLinesCollector collector(style, isRowAxis, autoRepeatTotalTracks);
1154     auto list = CSSValueList::createSpaceSeparated();
1155     unsigned insertionIndex;
1156     if (isRenderGrid) {
1157         auto computedTrackSizes = downcast<RenderGrid>(*renderer).trackSizesForComputedStyle(direction);
1158         unsigned numTracks = computedTrackSizes.size();
1159
1160         for (unsigned i = 0; i < numTracks; ++i) {
1161             addValuesForNamedGridLinesAtIndex(collector, i, list.get());
1162             list->append(zoomAdjustedPixelValue(computedTrackSizes[i], style));
1163         }
1164         addValuesForNamedGridLinesAtIndex(collector, numTracks + 1, list.get());
1165         insertionIndex = numTracks;
1166     } else {
1167         for (unsigned i = 0; i < trackSizes.size(); ++i) {
1168             addValuesForNamedGridLinesAtIndex(collector, i, list.get());
1169             list->append(specifiedValueForGridTrackSize(trackSizes[i], style));
1170         }
1171         insertionIndex = trackSizes.size();
1172     }
1173
1174     // Those are the trailing <ident>* allowed in the syntax.
1175     addValuesForNamedGridLinesAtIndex(collector, insertionIndex, list.get());
1176     return WTFMove(list);
1177 }
1178
1179 static Ref<CSSValue> valueForGridPosition(const GridPosition& position)
1180 {
1181     auto& cssValuePool = CSSValuePool::singleton();
1182     if (position.isAuto())
1183         return cssValuePool.createIdentifierValue(CSSValueAuto);
1184
1185     if (position.isNamedGridArea())
1186         return cssValuePool.createValue(position.namedGridLine(), CSSPrimitiveValue::CSS_STRING);
1187
1188     auto list = CSSValueList::createSpaceSeparated();
1189     if (position.isSpan()) {
1190         list->append(cssValuePool.createIdentifierValue(CSSValueSpan));
1191         list->append(cssValuePool.createValue(position.spanPosition(), CSSPrimitiveValue::CSS_NUMBER));
1192     } else
1193         list->append(cssValuePool.createValue(position.integerPosition(), CSSPrimitiveValue::CSS_NUMBER));
1194
1195     if (!position.namedGridLine().isNull())
1196         list->append(cssValuePool.createValue(position.namedGridLine(), CSSPrimitiveValue::CSS_STRING));
1197     return WTFMove(list);
1198 }
1199
1200 static Ref<CSSValue> createTransitionPropertyValue(const Animation& animation)
1201 {
1202     switch (animation.animationMode()) {
1203     case Animation::AnimateNone:
1204         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
1205     case Animation::AnimateAll:
1206         return CSSValuePool::singleton().createIdentifierValue(CSSValueAll);
1207     case Animation::AnimateSingleProperty:
1208         return CSSValuePool::singleton().createValue(getPropertyNameString(animation.property()), CSSPrimitiveValue::CSS_STRING);
1209     case Animation::AnimateUnknownProperty:
1210         return CSSValuePool::singleton().createValue(animation.unknownProperty(), CSSPrimitiveValue::CSS_STRING);
1211     }
1212     ASSERT_NOT_REACHED();
1213     return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
1214 }
1215
1216 static Ref<CSSValueList> transitionPropertyValue(const AnimationList* animationList)
1217 {
1218     auto list = CSSValueList::createCommaSeparated();
1219     if (animationList) {
1220         for (size_t i = 0; i < animationList->size(); ++i)
1221             list->append(createTransitionPropertyValue(animationList->animation(i)));
1222     } else
1223         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueAll));
1224     return list;
1225 }
1226
1227 #if ENABLE(CSS_SCROLL_SNAP)
1228
1229 static Ref<CSSValueList> valueForScrollSnapType(const ScrollSnapType& type)
1230 {
1231     auto value = CSSValueList::createSpaceSeparated();
1232     if (type.strictness == ScrollSnapStrictness::None)
1233         value->append(CSSValuePool::singleton().createValue(CSSValueNone));
1234     else {
1235         value->append(CSSPrimitiveValue::create(type.axis));
1236         value->append(CSSPrimitiveValue::create(type.strictness));
1237     }
1238     return value;
1239 }
1240
1241 static Ref<CSSValueList> valueForScrollSnapAlignment(const ScrollSnapAlign& alignment)
1242 {
1243     auto value = CSSValueList::createSpaceSeparated();
1244     value->append(CSSPrimitiveValue::create(alignment.x));
1245     value->append(CSSPrimitiveValue::create(alignment.y));
1246     return value;
1247 }
1248
1249 #endif
1250
1251 static Ref<CSSValue> willChangePropertyValue(const WillChangeData* willChangeData)
1252 {
1253     auto& cssValuePool = CSSValuePool::singleton();
1254     if (!willChangeData || !willChangeData->numFeatures())
1255         return cssValuePool.createIdentifierValue(CSSValueAuto);
1256
1257     auto list = CSSValueList::createCommaSeparated();
1258     for (size_t i = 0; i < willChangeData->numFeatures(); ++i) {
1259         WillChangeData::FeaturePropertyPair feature = willChangeData->featureAt(i);
1260         switch (feature.first) {
1261         case WillChangeData::ScrollPosition:
1262             list->append(cssValuePool.createIdentifierValue(CSSValueScrollPosition));
1263             break;
1264         case WillChangeData::Contents:
1265             list->append(cssValuePool.createIdentifierValue(CSSValueContents));
1266             break;
1267         case WillChangeData::Property:
1268             list->append(cssValuePool.createIdentifierValue(feature.second));
1269             break;
1270         case WillChangeData::Invalid:
1271             ASSERT_NOT_REACHED();
1272             break;
1273         }
1274     }
1275
1276     return WTFMove(list);
1277 }
1278
1279 static inline void appendLigaturesValue(CSSValueList& list, FontVariantLigatures value, CSSValueID yesValue, CSSValueID noValue)
1280 {
1281     switch (value) {
1282     case FontVariantLigatures::Normal:
1283         return;
1284     case FontVariantLigatures::No:
1285         list.append(CSSValuePool::singleton().createIdentifierValue(noValue));
1286         return;
1287     case FontVariantLigatures::Yes:
1288         list.append(CSSValuePool::singleton().createIdentifierValue(yesValue));
1289         return;
1290     }
1291     ASSERT_NOT_REACHED();
1292 }
1293
1294 static Ref<CSSValue> fontVariantLigaturesPropertyValue(FontVariantLigatures common, FontVariantLigatures discretionary, FontVariantLigatures historical, FontVariantLigatures contextualAlternates)
1295 {
1296     auto& cssValuePool = CSSValuePool::singleton();
1297     if (common == FontVariantLigatures::No && discretionary == FontVariantLigatures::No && historical == FontVariantLigatures::No && contextualAlternates == FontVariantLigatures::No)
1298         return cssValuePool.createIdentifierValue(CSSValueNone);
1299     if (common == FontVariantLigatures::Normal && discretionary == FontVariantLigatures::Normal && historical == FontVariantLigatures::Normal && contextualAlternates == FontVariantLigatures::Normal)
1300         return cssValuePool.createIdentifierValue(CSSValueNormal);
1301
1302     auto valueList = CSSValueList::createSpaceSeparated();
1303     appendLigaturesValue(valueList, common, CSSValueCommonLigatures, CSSValueNoCommonLigatures);
1304     appendLigaturesValue(valueList, discretionary, CSSValueDiscretionaryLigatures, CSSValueNoDiscretionaryLigatures);
1305     appendLigaturesValue(valueList, historical, CSSValueHistoricalLigatures, CSSValueNoHistoricalLigatures);
1306     appendLigaturesValue(valueList, contextualAlternates, CSSValueContextual, CSSValueNoContextual);
1307     return WTFMove(valueList);
1308 }
1309
1310 static Ref<CSSValue> fontVariantPositionPropertyValue(FontVariantPosition position)
1311 {
1312     auto& cssValuePool = CSSValuePool::singleton();
1313     CSSValueID valueID = CSSValueNormal;
1314     switch (position) {
1315     case FontVariantPosition::Normal:
1316         break;
1317     case FontVariantPosition::Subscript:
1318         valueID = CSSValueSub;
1319         break;
1320     case FontVariantPosition::Superscript:
1321         valueID = CSSValueSuper;
1322         break;
1323     }
1324     return cssValuePool.createIdentifierValue(valueID);
1325 }
1326
1327 static Ref<CSSValue> fontVariantCapsPropertyValue(FontVariantCaps caps)
1328 {
1329     auto& cssValuePool = CSSValuePool::singleton();
1330     CSSValueID valueID = CSSValueNormal;
1331     switch (caps) {
1332     case FontVariantCaps::Normal:
1333         break;
1334     case FontVariantCaps::Small:
1335         valueID = CSSValueSmallCaps;
1336         break;
1337     case FontVariantCaps::AllSmall:
1338         valueID = CSSValueAllSmallCaps;
1339         break;
1340     case FontVariantCaps::Petite:
1341         valueID = CSSValuePetiteCaps;
1342         break;
1343     case FontVariantCaps::AllPetite:
1344         valueID = CSSValueAllPetiteCaps;
1345         break;
1346     case FontVariantCaps::Unicase:
1347         valueID = CSSValueUnicase;
1348         break;
1349     case FontVariantCaps::Titling:
1350         valueID = CSSValueTitlingCaps;
1351         break;
1352     }
1353     return cssValuePool.createIdentifierValue(valueID);
1354 }
1355
1356 static Ref<CSSValue> fontVariantNumericPropertyValue(FontVariantNumericFigure figure, FontVariantNumericSpacing spacing, FontVariantNumericFraction fraction, FontVariantNumericOrdinal ordinal, FontVariantNumericSlashedZero slashedZero)
1357 {
1358     auto& cssValuePool = CSSValuePool::singleton();
1359     if (figure == FontVariantNumericFigure::Normal && spacing == FontVariantNumericSpacing::Normal && fraction == FontVariantNumericFraction::Normal && ordinal == FontVariantNumericOrdinal::Normal && slashedZero == FontVariantNumericSlashedZero::Normal)
1360         return cssValuePool.createIdentifierValue(CSSValueNormal);
1361
1362     auto valueList = CSSValueList::createSpaceSeparated();
1363     switch (figure) {
1364     case FontVariantNumericFigure::Normal:
1365         break;
1366     case FontVariantNumericFigure::LiningNumbers:
1367         valueList->append(cssValuePool.createIdentifierValue(CSSValueLiningNums));
1368         break;
1369     case FontVariantNumericFigure::OldStyleNumbers:
1370         valueList->append(cssValuePool.createIdentifierValue(CSSValueOldstyleNums));
1371         break;
1372     }
1373
1374     switch (spacing) {
1375     case FontVariantNumericSpacing::Normal:
1376         break;
1377     case FontVariantNumericSpacing::ProportionalNumbers:
1378         valueList->append(cssValuePool.createIdentifierValue(CSSValueProportionalNums));
1379         break;
1380     case FontVariantNumericSpacing::TabularNumbers:
1381         valueList->append(cssValuePool.createIdentifierValue(CSSValueTabularNums));
1382         break;
1383     }
1384
1385     switch (fraction) {
1386     case FontVariantNumericFraction::Normal:
1387         break;
1388     case FontVariantNumericFraction::DiagonalFractions:
1389         valueList->append(cssValuePool.createIdentifierValue(CSSValueDiagonalFractions));
1390         break;
1391     case FontVariantNumericFraction::StackedFractions:
1392         valueList->append(cssValuePool.createIdentifierValue(CSSValueStackedFractions));
1393         break;
1394     }
1395
1396     if (ordinal == FontVariantNumericOrdinal::Yes)
1397         valueList->append(cssValuePool.createIdentifierValue(CSSValueOrdinal));
1398     if (slashedZero == FontVariantNumericSlashedZero::Yes)
1399         valueList->append(cssValuePool.createIdentifierValue(CSSValueSlashedZero));
1400
1401     return WTFMove(valueList);
1402 }
1403
1404 static Ref<CSSValue> fontVariantAlternatesPropertyValue(FontVariantAlternates alternates)
1405 {
1406     auto& cssValuePool = CSSValuePool::singleton();
1407     CSSValueID valueID = CSSValueNormal;
1408     switch (alternates) {
1409     case FontVariantAlternates::Normal:
1410         break;
1411     case FontVariantAlternates::HistoricalForms:
1412         valueID = CSSValueHistoricalForms;
1413         break;
1414     }
1415     return cssValuePool.createIdentifierValue(valueID);
1416 }
1417
1418 static Ref<CSSValue> fontVariantEastAsianPropertyValue(FontVariantEastAsianVariant variant, FontVariantEastAsianWidth width, FontVariantEastAsianRuby ruby)
1419 {
1420     auto& cssValuePool = CSSValuePool::singleton();
1421     if (variant == FontVariantEastAsianVariant::Normal && width == FontVariantEastAsianWidth::Normal && ruby == FontVariantEastAsianRuby::Normal)
1422         return cssValuePool.createIdentifierValue(CSSValueNormal);
1423
1424     auto valueList = CSSValueList::createSpaceSeparated();
1425     switch (variant) {
1426     case FontVariantEastAsianVariant::Normal:
1427         break;
1428     case FontVariantEastAsianVariant::Jis78:
1429         valueList->append(cssValuePool.createIdentifierValue(CSSValueJis78));
1430         break;
1431     case FontVariantEastAsianVariant::Jis83:
1432         valueList->append(cssValuePool.createIdentifierValue(CSSValueJis83));
1433         break;
1434     case FontVariantEastAsianVariant::Jis90:
1435         valueList->append(cssValuePool.createIdentifierValue(CSSValueJis90));
1436         break;
1437     case FontVariantEastAsianVariant::Jis04:
1438         valueList->append(cssValuePool.createIdentifierValue(CSSValueJis04));
1439         break;
1440     case FontVariantEastAsianVariant::Simplified:
1441         valueList->append(cssValuePool.createIdentifierValue(CSSValueSimplified));
1442         break;
1443     case FontVariantEastAsianVariant::Traditional:
1444         valueList->append(cssValuePool.createIdentifierValue(CSSValueTraditional));
1445         break;
1446     }
1447
1448     switch (width) {
1449     case FontVariantEastAsianWidth::Normal:
1450         break;
1451     case FontVariantEastAsianWidth::Full:
1452         valueList->append(cssValuePool.createIdentifierValue(CSSValueFullWidth));
1453         break;
1454     case FontVariantEastAsianWidth::Proportional:
1455         valueList->append(cssValuePool.createIdentifierValue(CSSValueProportionalWidth));
1456         break;
1457     }
1458
1459     if (ruby == FontVariantEastAsianRuby::Yes)
1460         valueList->append(cssValuePool.createIdentifierValue(CSSValueRuby));
1461
1462     return WTFMove(valueList);
1463 }
1464
1465 static Ref<CSSValueList> delayValue(const AnimationList* animationList)
1466 {
1467     auto& cssValuePool = CSSValuePool::singleton();
1468     auto list = CSSValueList::createCommaSeparated();
1469     if (animationList) {
1470         for (size_t i = 0; i < animationList->size(); ++i)
1471             list->append(cssValuePool.createValue(animationList->animation(i).delay(), CSSPrimitiveValue::CSS_S));
1472     } else {
1473         // Note that initialAnimationDelay() is used for both transitions and animations
1474         list->append(cssValuePool.createValue(Animation::initialDelay(), CSSPrimitiveValue::CSS_S));
1475     }
1476     return list;
1477 }
1478
1479 static Ref<CSSValueList> durationValue(const AnimationList* animationList)
1480 {
1481     auto& cssValuePool = CSSValuePool::singleton();
1482     auto list = CSSValueList::createCommaSeparated();
1483     if (animationList) {
1484         for (size_t i = 0; i < animationList->size(); ++i)
1485             list->append(cssValuePool.createValue(animationList->animation(i).duration(), CSSPrimitiveValue::CSS_S));
1486     } else {
1487         // Note that initialAnimationDuration() is used for both transitions and animations
1488         list->append(cssValuePool.createValue(Animation::initialDuration(), CSSPrimitiveValue::CSS_S));
1489     }
1490     return list;
1491 }
1492
1493 static Ref<CSSValue> createTimingFunctionValue(const TimingFunction& timingFunction)
1494 {
1495     switch (timingFunction.type()) {
1496     case TimingFunction::CubicBezierFunction: {
1497         auto& function = static_cast<const CubicBezierTimingFunction&>(timingFunction);
1498         if (function.timingFunctionPreset() != CubicBezierTimingFunction::Custom) {
1499             CSSValueID valueId = CSSValueInvalid;
1500             switch (function.timingFunctionPreset()) {
1501             case CubicBezierTimingFunction::Ease:
1502                 valueId = CSSValueEase;
1503                 break;
1504             case CubicBezierTimingFunction::EaseIn:
1505                 valueId = CSSValueEaseIn;
1506                 break;
1507             case CubicBezierTimingFunction::EaseOut:
1508                 valueId = CSSValueEaseOut;
1509                 break;
1510             default:
1511                 ASSERT(function.timingFunctionPreset() == CubicBezierTimingFunction::EaseInOut);
1512                 valueId = CSSValueEaseInOut;
1513                 break;
1514             }
1515             return CSSValuePool::singleton().createIdentifierValue(valueId);
1516         }
1517         return CSSCubicBezierTimingFunctionValue::create(function.x1(), function.y1(), function.x2(), function.y2());
1518     }
1519     case TimingFunction::StepsFunction: {
1520         auto& function = static_cast<const StepsTimingFunction&>(timingFunction);
1521         return CSSStepsTimingFunctionValue::create(function.numberOfSteps(), function.stepAtStart());
1522     }
1523     case TimingFunction::SpringFunction: {
1524         auto& function = static_cast<const SpringTimingFunction&>(timingFunction);
1525         return CSSSpringTimingFunctionValue::create(function.mass(), function.stiffness(), function.damping(), function.initialVelocity());
1526     }
1527     default:
1528         ASSERT(timingFunction.type() == TimingFunction::LinearFunction);
1529         return CSSValuePool::singleton().createIdentifierValue(CSSValueLinear);
1530     }
1531 }
1532
1533 static Ref<CSSValueList> timingFunctionValue(const AnimationList* animationList)
1534 {
1535     auto list = CSSValueList::createCommaSeparated();
1536     if (animationList) {
1537         for (size_t i = 0; i < animationList->size(); ++i)
1538             list->append(createTimingFunctionValue(*animationList->animation(i).timingFunction()));
1539     } else
1540         // Note that initialAnimationTimingFunction() is used for both transitions and animations
1541         list->append(createTimingFunctionValue(Animation::initialTimingFunction()));
1542     return list;
1543 }
1544
1545 #if ENABLE(CSS_ANIMATIONS_LEVEL_2)
1546
1547 static Ref<CSSValue> createAnimationTriggerValue(const AnimationTrigger& trigger, const RenderStyle& style)
1548 {
1549     switch (trigger.type()) {
1550     case AnimationTrigger::AnimationTriggerType::ScrollAnimationTriggerType: {
1551         auto& scrollAnimationTrigger = downcast<ScrollAnimationTrigger>(trigger);
1552         if (scrollAnimationTrigger.endValue().isAuto())
1553             return CSSAnimationTriggerScrollValue::create(zoomAdjustedPixelValueForLength(scrollAnimationTrigger.startValue(), style));
1554         return CSSAnimationTriggerScrollValue::create(zoomAdjustedPixelValueForLength(scrollAnimationTrigger.startValue(), style),
1555                                                       zoomAdjustedPixelValueForLength(scrollAnimationTrigger.endValue(), style));
1556     }
1557     default:
1558         ASSERT(trigger.type() == AnimationTrigger::AnimationTriggerType::AutoAnimationTriggerType);
1559         return CSSValuePool::singleton().createIdentifierValue(CSSValueAuto);
1560     }
1561 }
1562
1563 static Ref<CSSValueList> animationTriggerValue(const AnimationList* animationList, const RenderStyle& style)
1564 {
1565     auto list = CSSValueList::createCommaSeparated();
1566     if (animationList) {
1567         for (size_t i = 0; i < animationList->size(); ++i)
1568             list->append(createAnimationTriggerValue(*animationList->animation(i).trigger(), style));
1569     } else
1570         list->append(createAnimationTriggerValue(Animation::initialTrigger().get(), style));
1571     return list;
1572 }
1573
1574 #endif
1575
1576 static Ref<CSSValue> createLineBoxContainValue(unsigned lineBoxContain)
1577 {
1578     if (!lineBoxContain)
1579         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
1580     return CSSLineBoxContainValue::create(lineBoxContain);
1581 }
1582
1583 static Element* styleElementForNode(Node* node)
1584 {
1585     if (!node)
1586         return nullptr;
1587     if (is<Element>(*node))
1588         return downcast<Element>(node);
1589     return composedTreeAncestors(*node).first();
1590 }
1591
1592 ComputedStyleExtractor::ComputedStyleExtractor(Node* node, bool allowVisitedStyle, PseudoId pseudoElementSpecifier)
1593     : m_element(styleElementForNode(node))
1594     , m_pseudoElementSpecifier(pseudoElementSpecifier)
1595     , m_allowVisitedStyle(allowVisitedStyle)
1596 {
1597 }
1598
1599 ComputedStyleExtractor::ComputedStyleExtractor(Element* element, bool allowVisitedStyle, PseudoId pseudoElementSpecifier)
1600     : m_element(element)
1601     , m_pseudoElementSpecifier(pseudoElementSpecifier)
1602     , m_allowVisitedStyle(allowVisitedStyle)
1603 {
1604 }
1605
1606 CSSComputedStyleDeclaration::CSSComputedStyleDeclaration(Element& element, bool allowVisitedStyle, const String& pseudoElementName)
1607     : m_element(element)
1608     , m_allowVisitedStyle(allowVisitedStyle)
1609     , m_refCount(1)
1610 {
1611     unsigned nameWithoutColonsStart = pseudoElementName[0] == ':' ? (pseudoElementName[1] == ':' ? 2 : 1) : 0;
1612     m_pseudoElementSpecifier = CSSSelector::pseudoId(CSSSelector::parsePseudoElementType(
1613     (pseudoElementName.substringSharingImpl(nameWithoutColonsStart))));
1614 }
1615
1616 CSSComputedStyleDeclaration::~CSSComputedStyleDeclaration()
1617 {
1618 }
1619
1620 void CSSComputedStyleDeclaration::ref()
1621 {
1622     ++m_refCount;
1623 }
1624
1625 void CSSComputedStyleDeclaration::deref()
1626 {
1627     ASSERT(m_refCount);
1628     if (!--m_refCount)
1629         delete this;
1630 }
1631
1632 String CSSComputedStyleDeclaration::cssText() const
1633 {
1634     StringBuilder result;
1635
1636     for (unsigned i = 0; i < numComputedProperties; i++) {
1637         if (i)
1638             result.append(' ');
1639         result.append(getPropertyName(computedProperties[i]));
1640         result.appendLiteral(": ");
1641         result.append(getPropertyValue(computedProperties[i]));
1642         result.append(';');
1643     }
1644
1645     return result.toString();
1646 }
1647
1648 ExceptionOr<void> CSSComputedStyleDeclaration::setCssText(const String&)
1649 {
1650     return Exception { NO_MODIFICATION_ALLOWED_ERR };
1651 }
1652
1653 RefPtr<CSSPrimitiveValue> ComputedStyleExtractor::getFontSizeCSSValuePreferringKeyword()
1654 {
1655     if (!m_element)
1656         return nullptr;
1657
1658     m_element->document().updateLayoutIgnorePendingStylesheets();
1659
1660     auto* style = m_element->computedStyle(m_pseudoElementSpecifier);
1661     if (!style)
1662         return nullptr;
1663
1664     if (CSSValueID sizeIdentifier = style->fontDescription().keywordSizeAsIdentifier())
1665         return CSSValuePool::singleton().createIdentifierValue(sizeIdentifier);
1666
1667     return zoomAdjustedPixelValue(style->fontDescription().computedSize(), *style);
1668 }
1669
1670 bool ComputedStyleExtractor::useFixedFontDefaultSize()
1671 {
1672     if (!m_element)
1673         return false;
1674     auto* style = m_element->computedStyle(m_pseudoElementSpecifier);
1675     if (!style)
1676         return false;
1677
1678     return style->fontDescription().useFixedDefaultSize();
1679 }
1680
1681
1682 static CSSValueID identifierForFamily(const AtomicString& family)
1683 {
1684     if (family == cursiveFamily)
1685         return CSSValueCursive;
1686     if (family == fantasyFamily)
1687         return CSSValueFantasy;
1688     if (family == monospaceFamily)
1689         return CSSValueMonospace;
1690     if (family == pictographFamily)
1691         return CSSValueWebkitPictograph;
1692     if (family == sansSerifFamily)
1693         return CSSValueSansSerif;
1694     if (family == serifFamily)
1695         return CSSValueSerif;
1696     if (family == systemUiFamily)
1697         return CSSValueSystemUi;
1698     return CSSValueInvalid;
1699 }
1700
1701 static Ref<CSSPrimitiveValue> valueForFamily(const AtomicString& family)
1702 {
1703     if (CSSValueID familyIdentifier = identifierForFamily(family))
1704         return CSSValuePool::singleton().createIdentifierValue(familyIdentifier);
1705     return CSSValuePool::singleton().createFontFamilyValue(family);
1706 }
1707
1708 static Ref<CSSValue> renderTextDecorationFlagsToCSSValue(int textDecoration)
1709 {
1710     auto& cssValuePool = CSSValuePool::singleton();
1711     // Blink value is ignored.
1712     auto list = CSSValueList::createSpaceSeparated();
1713     if (textDecoration & TextDecorationUnderline)
1714         list->append(cssValuePool.createIdentifierValue(CSSValueUnderline));
1715     if (textDecoration & TextDecorationOverline)
1716         list->append(cssValuePool.createIdentifierValue(CSSValueOverline));
1717     if (textDecoration & TextDecorationLineThrough)
1718         list->append(cssValuePool.createIdentifierValue(CSSValueLineThrough));
1719 #if ENABLE(LETTERPRESS)
1720     if (textDecoration & TextDecorationLetterpress)
1721         list->append(cssValuePool.createIdentifierValue(CSSValueWebkitLetterpress));
1722 #endif
1723
1724     if (!list->length())
1725         return cssValuePool.createIdentifierValue(CSSValueNone);
1726     return WTFMove(list);
1727 }
1728
1729 static Ref<CSSValue> renderTextDecorationStyleFlagsToCSSValue(TextDecorationStyle textDecorationStyle)
1730 {
1731     switch (textDecorationStyle) {
1732     case TextDecorationStyleSolid:
1733         return CSSValuePool::singleton().createIdentifierValue(CSSValueSolid);
1734     case TextDecorationStyleDouble:
1735         return CSSValuePool::singleton().createIdentifierValue(CSSValueDouble);
1736     case TextDecorationStyleDotted:
1737         return CSSValuePool::singleton().createIdentifierValue(CSSValueDotted);
1738     case TextDecorationStyleDashed:
1739         return CSSValuePool::singleton().createIdentifierValue(CSSValueDashed);
1740     case TextDecorationStyleWavy:
1741         return CSSValuePool::singleton().createIdentifierValue(CSSValueWavy);
1742     }
1743
1744     ASSERT_NOT_REACHED();
1745     return CSSValuePool::singleton().createExplicitInitialValue();
1746 }
1747
1748 static Ref<CSSValue> renderTextDecorationSkipFlagsToCSSValue(TextDecorationSkip textDecorationSkip)
1749 {
1750     switch (textDecorationSkip) {
1751     case TextDecorationSkipAuto:
1752         return CSSValuePool::singleton().createIdentifierValue(CSSValueAuto);
1753     case TextDecorationSkipNone:
1754         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
1755     case TextDecorationSkipInk:
1756         return CSSValuePool::singleton().createIdentifierValue(CSSValueInk);
1757     case TextDecorationSkipObjects:
1758         return CSSValuePool::singleton().createIdentifierValue(CSSValueObjects);
1759     }
1760
1761     ASSERT_NOT_REACHED();
1762     return CSSValuePool::singleton().createExplicitInitialValue();
1763 }
1764
1765 static Ref<CSSValue> renderEmphasisPositionFlagsToCSSValue(TextEmphasisPosition textEmphasisPosition)
1766 {
1767     ASSERT(!((textEmphasisPosition & TextEmphasisPositionOver) && (textEmphasisPosition & TextEmphasisPositionUnder)));
1768     ASSERT(!((textEmphasisPosition & TextEmphasisPositionLeft) && (textEmphasisPosition & TextEmphasisPositionRight)));
1769     auto& cssValuePool = CSSValuePool::singleton();
1770     auto list = CSSValueList::createSpaceSeparated();
1771     if (textEmphasisPosition & TextEmphasisPositionOver)
1772         list->append(cssValuePool.createIdentifierValue(CSSValueOver));
1773     if (textEmphasisPosition & TextEmphasisPositionUnder)
1774         list->append(cssValuePool.createIdentifierValue(CSSValueUnder));
1775     if (textEmphasisPosition & TextEmphasisPositionLeft)
1776         list->append(cssValuePool.createIdentifierValue(CSSValueLeft));
1777     if (textEmphasisPosition & TextEmphasisPositionRight)
1778         list->append(cssValuePool.createIdentifierValue(CSSValueRight));
1779     if (!list->length())
1780         return cssValuePool.createIdentifierValue(CSSValueNone);
1781     return WTFMove(list);
1782 }
1783
1784 static Ref<CSSValue> hangingPunctuationToCSSValue(HangingPunctuation hangingPunctuation)
1785 {
1786     auto& cssValuePool = CSSValuePool::singleton();
1787     auto list = CSSValueList::createSpaceSeparated();
1788     if (hangingPunctuation & FirstHangingPunctuation)
1789         list->append(cssValuePool.createIdentifierValue(CSSValueFirst));
1790     if (hangingPunctuation & AllowEndHangingPunctuation)
1791         list->append(cssValuePool.createIdentifierValue(CSSValueAllowEnd));
1792     if (hangingPunctuation & ForceEndHangingPunctuation)
1793         list->append(cssValuePool.createIdentifierValue(CSSValueForceEnd));
1794     if (hangingPunctuation & LastHangingPunctuation)
1795         list->append(cssValuePool.createIdentifierValue(CSSValueLast));
1796     if (!list->length())
1797         return cssValuePool.createIdentifierValue(CSSValueNone);
1798     return WTFMove(list);
1799 }
1800     
1801 static Ref<CSSValue> fillRepeatToCSSValue(EFillRepeat xRepeat, EFillRepeat yRepeat)
1802 {
1803     // For backwards compatibility, if both values are equal, just return one of them. And
1804     // if the two values are equivalent to repeat-x or repeat-y, just return the shorthand.
1805     auto& cssValuePool = CSSValuePool::singleton();
1806     if (xRepeat == yRepeat)
1807         return cssValuePool.createValue(xRepeat);
1808     if (xRepeat == RepeatFill && yRepeat == NoRepeatFill)
1809         return cssValuePool.createIdentifierValue(CSSValueRepeatX);
1810     if (xRepeat == NoRepeatFill && yRepeat == RepeatFill)
1811         return cssValuePool.createIdentifierValue(CSSValueRepeatY);
1812
1813     auto list = CSSValueList::createSpaceSeparated();
1814     list->append(cssValuePool.createValue(xRepeat));
1815     list->append(cssValuePool.createValue(yRepeat));
1816     return WTFMove(list);
1817 }
1818
1819 static Ref<CSSValue> fillSourceTypeToCSSValue(EMaskSourceType type)
1820 {
1821     switch (type) {
1822     case MaskAlpha:
1823         return CSSValuePool::singleton().createValue(CSSValueAlpha);
1824     default:
1825         ASSERT(type == MaskLuminance);
1826         return CSSValuePool::singleton().createValue(CSSValueLuminance);
1827     }
1828 }
1829
1830 static Ref<CSSValue> fillSizeToCSSValue(const FillSize& fillSize, const RenderStyle& style)
1831 {
1832     if (fillSize.type == Contain)
1833         return CSSValuePool::singleton().createIdentifierValue(CSSValueContain);
1834
1835     if (fillSize.type == Cover)
1836         return CSSValuePool::singleton().createIdentifierValue(CSSValueCover);
1837
1838     if (fillSize.size.height.isAuto())
1839         return zoomAdjustedPixelValueForLength(fillSize.size.width, style);
1840
1841     auto list = CSSValueList::createSpaceSeparated();
1842     list->append(zoomAdjustedPixelValueForLength(fillSize.size.width, style));
1843     list->append(zoomAdjustedPixelValueForLength(fillSize.size.height, style));
1844     return WTFMove(list);
1845 }
1846
1847 static Ref<CSSValue> altTextToCSSValue(const RenderStyle& style)
1848 {
1849     return CSSValuePool::singleton().createValue(style.contentAltText(), CSSPrimitiveValue::CSS_STRING);
1850 }
1851     
1852 static Ref<CSSValueList> contentToCSSValue(const RenderStyle& style)
1853 {
1854     auto& cssValuePool = CSSValuePool::singleton();
1855     auto list = CSSValueList::createSpaceSeparated();
1856     for (auto* contentData = style.contentData(); contentData; contentData = contentData->next()) {
1857         if (is<CounterContentData>(*contentData))
1858             list->append(cssValuePool.createValue(downcast<CounterContentData>(*contentData).counter().identifier(), CSSPrimitiveValue::CSS_COUNTER_NAME));
1859         else if (is<ImageContentData>(*contentData))
1860             list->append(downcast<ImageContentData>(*contentData).image().cssValue());
1861         else if (is<TextContentData>(*contentData))
1862             list->append(cssValuePool.createValue(downcast<TextContentData>(*contentData).text(), CSSPrimitiveValue::CSS_STRING));
1863     }
1864     if (style.hasFlowFrom())
1865         list->append(cssValuePool.createValue(style.regionThread(), CSSPrimitiveValue::CSS_STRING));
1866     return list;
1867 }
1868
1869 static Ref<CSSValue> counterToCSSValue(const RenderStyle& style, CSSPropertyID propertyID)
1870 {
1871     auto* map = style.counterDirectives();
1872     if (!map)
1873         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
1874
1875     auto& cssValuePool = CSSValuePool::singleton();
1876     auto list = CSSValueList::createSpaceSeparated();
1877     for (CounterDirectiveMap::const_iterator it = map->begin(); it != map->end(); ++it) {
1878         list->append(cssValuePool.createValue(it->key, CSSPrimitiveValue::CSS_STRING));
1879         short number = propertyID == CSSPropertyCounterIncrement ? it->value.incrementValue() : it->value.resetValue();
1880         list->append(cssValuePool.createValue((double)number, CSSPrimitiveValue::CSS_NUMBER));
1881     }
1882     return WTFMove(list);
1883 }
1884
1885 static void logUnimplementedPropertyID(CSSPropertyID propertyID)
1886 {
1887     static NeverDestroyed<HashSet<CSSPropertyID>> propertyIDSet;
1888     if (!propertyIDSet.get().add(propertyID).isNewEntry)
1889         return;
1890
1891     LOG_ERROR("WebKit does not yet implement getComputedStyle for '%s'.", getPropertyName(propertyID));
1892 }
1893
1894 static Ref<CSSValueList> fontFamilyListFromStyle(const RenderStyle& style)
1895 {
1896     auto list = CSSValueList::createCommaSeparated();
1897     for (unsigned i = 0; i < style.fontCascade().familyCount(); ++i)
1898         list->append(valueForFamily(style.fontCascade().familyAt(i)));
1899     return list;
1900 }
1901
1902 static Ref<CSSValue> fontFamilyFromStyle(const RenderStyle& style)
1903 {
1904     if (style.fontCascade().familyCount() == 1)
1905         return valueForFamily(style.fontCascade().familyAt(0));
1906     return fontFamilyListFromStyle(style);
1907 }
1908
1909 static Ref<CSSPrimitiveValue> lineHeightFromStyle(const RenderStyle& style)
1910 {
1911     Length length = style.lineHeight();
1912     if (length.isNegative()) // If true, line-height not set; use the font's line spacing.
1913         return zoomAdjustedPixelValue(style.fontMetrics().floatLineSpacing(), style);
1914     if (length.isPercent()) {
1915         // This is imperfect, because it doesn't include the zoom factor and the real computation
1916         // for how high to be in pixels does include things like minimum font size and the zoom factor.
1917         // On the other hand, since font-size doesn't include the zoom factor, we really can't do
1918         // that here either.
1919         return zoomAdjustedPixelValue(static_cast<int>(length.percent() * style.fontDescription().specifiedSize()) / 100, style);
1920     }
1921     return zoomAdjustedPixelValue(floatValueForLength(length, 0), style);
1922 }
1923
1924 static Ref<CSSPrimitiveValue> fontSizeFromStyle(const RenderStyle& style)
1925 {
1926     return zoomAdjustedPixelValue(style.fontDescription().computedSize(), style);
1927 }
1928
1929 Ref<CSSPrimitiveValue> ComputedStyleExtractor::fontNonKeywordWeightFromStyleValue(FontSelectionValue weight)
1930 {
1931     return CSSValuePool::singleton().createValue(static_cast<float>(weight), CSSPrimitiveValue::CSS_NUMBER);
1932 }
1933
1934 Ref<CSSPrimitiveValue> ComputedStyleExtractor::fontWeightFromStyleValue(FontSelectionValue weight)
1935 {
1936     if (auto value = fontWeightKeyword(weight))
1937         return CSSValuePool::singleton().createIdentifierValue(value.value());
1938     return fontNonKeywordWeightFromStyleValue(weight);
1939 }
1940
1941 static Ref<CSSPrimitiveValue> fontWeightFromStyle(const RenderStyle& style)
1942 {
1943     return ComputedStyleExtractor::fontWeightFromStyleValue(style.fontDescription().weight());
1944 }
1945
1946 Ref<CSSPrimitiveValue> ComputedStyleExtractor::fontNonKeywordStretchFromStyleValue(FontSelectionValue stretch)
1947 {
1948     return CSSValuePool::singleton().createValue(static_cast<float>(stretch), CSSPrimitiveValue::CSS_PERCENTAGE);
1949 }
1950
1951 Ref<CSSPrimitiveValue> ComputedStyleExtractor::fontStretchFromStyleValue(FontSelectionValue stretch)
1952 {
1953     if (auto keyword = fontStretchKeyword(stretch))
1954         return CSSValuePool::singleton().createIdentifierValue(keyword.value());
1955     return fontNonKeywordStretchFromStyleValue(stretch);
1956 }
1957
1958 static Ref<CSSPrimitiveValue> fontStretchFromStyle(const RenderStyle& style)
1959 {
1960     return ComputedStyleExtractor::fontStretchFromStyleValue(style.fontDescription().stretch());
1961 }
1962
1963 Ref<CSSFontStyleValue> ComputedStyleExtractor::fontNonKeywordStyleFromStyleValue(FontSelectionValue italic)
1964 {
1965     return CSSFontStyleValue::create(CSSValuePool::singleton().createIdentifierValue(CSSValueOblique), CSSValuePool::singleton().createValue(static_cast<float>(italic), CSSPrimitiveValue::CSS_DEG));
1966 }
1967
1968 Ref<CSSFontStyleValue> ComputedStyleExtractor::fontStyleFromStyleValue(FontSelectionValue italic)
1969 {
1970     if (auto keyword = fontStyleKeyword(italic))
1971         return CSSFontStyleValue::create(CSSValuePool::singleton().createIdentifierValue(keyword.value()));
1972     return fontNonKeywordStyleFromStyleValue(italic);
1973 }
1974
1975 static Ref<CSSFontStyleValue> fontStyleFromStyle(const RenderStyle& style)
1976 {
1977     return ComputedStyleExtractor::fontStyleFromStyleValue(style.fontDescription().italic());
1978 }
1979
1980 static Ref<CSSValue> fontVariantFromStyle(const RenderStyle& style)
1981 {
1982     if (style.fontDescription().variantSettings().isAllNormal())
1983         return CSSValuePool::singleton().createIdentifierValue(CSSValueNormal);
1984
1985     auto list = CSSValueList::createSpaceSeparated();
1986
1987     switch (style.fontDescription().variantCommonLigatures()) {
1988     case FontVariantLigatures::Normal:
1989         break;
1990     case FontVariantLigatures::Yes:
1991         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueCommonLigatures));
1992         break;
1993     case FontVariantLigatures::No:
1994         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoCommonLigatures));
1995         break;
1996     }
1997
1998     switch (style.fontDescription().variantDiscretionaryLigatures()) {
1999     case FontVariantLigatures::Normal:
2000         break;
2001     case FontVariantLigatures::Yes:
2002         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueDiscretionaryLigatures));
2003         break;
2004     case FontVariantLigatures::No:
2005         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoDiscretionaryLigatures));
2006         break;
2007     }
2008
2009     switch (style.fontDescription().variantHistoricalLigatures()) {
2010     case FontVariantLigatures::Normal:
2011         break;
2012     case FontVariantLigatures::Yes:
2013         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueHistoricalLigatures));
2014         break;
2015     case FontVariantLigatures::No:
2016         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoHistoricalLigatures));
2017         break;
2018     }
2019
2020     switch (style.fontDescription().variantContextualAlternates()) {
2021     case FontVariantLigatures::Normal:
2022         break;
2023     case FontVariantLigatures::Yes:
2024         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueContextual));
2025         break;
2026     case FontVariantLigatures::No:
2027         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoContextual));
2028         break;
2029     }
2030
2031     switch (style.fontDescription().variantPosition()) {
2032     case FontVariantPosition::Normal:
2033         break;
2034     case FontVariantPosition::Subscript:
2035         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSub));
2036         break;
2037     case FontVariantPosition::Superscript:
2038         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSuper));
2039         break;
2040     }
2041
2042     switch (style.fontDescription().variantCaps()) {
2043     case FontVariantCaps::Normal:
2044         break;
2045     case FontVariantCaps::Small:
2046         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSmallCaps));
2047         break;
2048     case FontVariantCaps::AllSmall:
2049         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueAllSmallCaps));
2050         break;
2051     case FontVariantCaps::Petite:
2052         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValuePetiteCaps));
2053         break;
2054     case FontVariantCaps::AllPetite:
2055         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueAllPetiteCaps));
2056         break;
2057     case FontVariantCaps::Unicase:
2058         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueUnicase));
2059         break;
2060     case FontVariantCaps::Titling:
2061         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueTitlingCaps));
2062         break;
2063     }
2064
2065     switch (style.fontDescription().variantNumericFigure()) {
2066     case FontVariantNumericFigure::Normal:
2067         break;
2068     case FontVariantNumericFigure::LiningNumbers:
2069         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueLiningNums));
2070         break;
2071     case FontVariantNumericFigure::OldStyleNumbers:
2072         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueOldstyleNums));
2073         break;
2074     }
2075
2076     switch (style.fontDescription().variantNumericSpacing()) {
2077     case FontVariantNumericSpacing::Normal:
2078         break;
2079     case FontVariantNumericSpacing::ProportionalNumbers:
2080         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueProportionalNums));
2081         break;
2082     case FontVariantNumericSpacing::TabularNumbers:
2083         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueTabularNums));
2084         break;
2085     }
2086
2087     switch (style.fontDescription().variantNumericFraction()) {
2088     case FontVariantNumericFraction::Normal:
2089         break;
2090     case FontVariantNumericFraction::DiagonalFractions:
2091         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueDiagonalFractions));
2092         break;
2093     case FontVariantNumericFraction::StackedFractions:
2094         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueStackedFractions));
2095         break;
2096     }
2097
2098     switch (style.fontDescription().variantNumericOrdinal()) {
2099     case FontVariantNumericOrdinal::Normal:
2100         break;
2101     case FontVariantNumericOrdinal::Yes:
2102         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueOrdinal));
2103         break;
2104     }
2105
2106     switch (style.fontDescription().variantNumericSlashedZero()) {
2107     case FontVariantNumericSlashedZero::Normal:
2108         break;
2109     case FontVariantNumericSlashedZero::Yes:
2110         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSlashedZero));
2111         break;
2112     }
2113
2114     switch (style.fontDescription().variantAlternates()) {
2115     case FontVariantAlternates::Normal:
2116         break;
2117     case FontVariantAlternates::HistoricalForms:
2118         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueHistoricalForms));
2119         break;
2120     }
2121
2122     switch (style.fontDescription().variantEastAsianVariant()) {
2123     case FontVariantEastAsianVariant::Normal:
2124         break;
2125     case FontVariantEastAsianVariant::Jis78:
2126         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis78));
2127         break;
2128     case FontVariantEastAsianVariant::Jis83:
2129         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis83));
2130         break;
2131     case FontVariantEastAsianVariant::Jis90:
2132         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis90));
2133         break;
2134     case FontVariantEastAsianVariant::Jis04:
2135         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis04));
2136         break;
2137     case FontVariantEastAsianVariant::Simplified:
2138         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSimplified));
2139         break;
2140     case FontVariantEastAsianVariant::Traditional:
2141         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueTraditional));
2142         break;
2143     }
2144
2145     switch (style.fontDescription().variantEastAsianWidth()) {
2146     case FontVariantEastAsianWidth::Normal:
2147         break;
2148     case FontVariantEastAsianWidth::Full:
2149         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueFullWidth));
2150         break;
2151     case FontVariantEastAsianWidth::Proportional:
2152         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueProportionalWidth));
2153         break;
2154     }
2155
2156     switch (style.fontDescription().variantEastAsianRuby()) {
2157     case FontVariantEastAsianRuby::Normal:
2158         break;
2159     case FontVariantEastAsianRuby::Yes:
2160         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueRuby));
2161         break;
2162     }
2163
2164     return WTFMove(list);
2165 }
2166
2167 static Ref<CSSValue> fontSynthesisFromStyle(const RenderStyle& style)
2168 {
2169     if (style.fontDescription().fontSynthesis() == FontSynthesisNone)
2170         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
2171
2172     auto list = CSSValueList::createSpaceSeparated();
2173     if (style.fontDescription().fontSynthesis() & FontSynthesisStyle)
2174         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueStyle));
2175     if (style.fontDescription().fontSynthesis() & FontSynthesisWeight)
2176         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueWeight));
2177     if (style.fontDescription().fontSynthesis() & FontSynthesisSmallCaps)
2178         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSmallCaps));
2179     return WTFMove(list);
2180 }
2181
2182 typedef const Length& (RenderStyle::*RenderStyleLengthGetter)() const;
2183 typedef LayoutUnit (RenderBoxModelObject::*RenderBoxComputedCSSValueGetter)() const;
2184
2185 template<RenderStyleLengthGetter lengthGetter, RenderBoxComputedCSSValueGetter computedCSSValueGetter>
2186 static RefPtr<CSSValue> zoomAdjustedPaddingOrMarginPixelValue(const RenderStyle& style, RenderObject* renderer)
2187 {
2188     Length unzoomzedLength = (style.*lengthGetter)();
2189     if (!is<RenderBox>(renderer) || unzoomzedLength.isFixed())
2190         return zoomAdjustedPixelValueForLength(unzoomzedLength, style);
2191     return zoomAdjustedPixelValue((downcast<RenderBox>(*renderer).*computedCSSValueGetter)(), style);
2192 }
2193
2194 template<RenderStyleLengthGetter lengthGetter>
2195 static bool paddingOrMarginIsRendererDependent(const RenderStyle* style, RenderObject* renderer)
2196 {
2197     return renderer && style && renderer->isBox() && !(style->*lengthGetter)().isFixed();
2198 }
2199
2200 static CSSValueID convertToPageBreak(BreakBetween value)
2201 {
2202     if (value == PageBreakBetween || value == LeftPageBreakBetween || value == RightPageBreakBetween
2203         || value == RectoPageBreakBetween || value == VersoPageBreakBetween)
2204         return CSSValueAlways; // CSS 2.1 allows us to map these to always.
2205     if (value == AvoidBreakBetween || value == AvoidPageBreakBetween)
2206         return CSSValueAvoid;
2207     return CSSValueAuto;
2208 }
2209
2210 static CSSValueID convertToColumnBreak(BreakBetween value)
2211 {
2212     if (value == ColumnBreakBetween)
2213         return CSSValueAlways;
2214     if (value == AvoidBreakBetween || value == AvoidColumnBreakBetween)
2215         return CSSValueAvoid;
2216     return CSSValueAuto;
2217 }
2218
2219 static CSSValueID convertToPageBreak(BreakInside value)
2220 {
2221     if (value == AvoidBreakInside || value == AvoidPageBreakInside)
2222         return CSSValueAvoid;
2223     return CSSValueAuto;
2224 }
2225
2226 static CSSValueID convertToColumnBreak(BreakInside value)
2227 {
2228     if (value == AvoidBreakInside || value == AvoidColumnBreakInside)
2229         return CSSValueAvoid;
2230     return CSSValueAuto;
2231 }
2232
2233 #if ENABLE(CSS_REGIONS)
2234 static CSSValueID convertToRegionBreak(BreakBetween value)
2235 {
2236     if (value == RegionBreakBetween)
2237         return CSSValueAlways;
2238     if (value == AvoidBreakBetween || value == AvoidRegionBreakBetween)
2239         return CSSValueAvoid;
2240     return CSSValueAuto;
2241 }
2242     
2243 static CSSValueID convertToRegionBreak(BreakInside value)
2244 {
2245     if (value == AvoidBreakInside || value == AvoidRegionBreakInside)
2246         return CSSValueAvoid;
2247     return CSSValueAuto;
2248 }
2249 #endif
2250     
2251 static bool isLayoutDependent(CSSPropertyID propertyID, const RenderStyle* style, RenderObject* renderer)
2252 {
2253     switch (propertyID) {
2254     case CSSPropertyWidth:
2255     case CSSPropertyHeight:
2256     case CSSPropertyPerspectiveOrigin:
2257     case CSSPropertyTransformOrigin:
2258     case CSSPropertyTransform:
2259     case CSSPropertyFilter:
2260 #if ENABLE(FILTERS_LEVEL_2)
2261     case CSSPropertyWebkitBackdropFilter:
2262 #endif
2263         return true;
2264     case CSSPropertyMargin: {
2265         if (!renderer || !renderer->isBox())
2266             return false;
2267         return !(style && style->marginTop().isFixed() && style->marginRight().isFixed()
2268             && style->marginBottom().isFixed() && style->marginLeft().isFixed());
2269     }
2270     case CSSPropertyMarginTop:
2271         return paddingOrMarginIsRendererDependent<&RenderStyle::marginTop>(style, renderer);
2272     case CSSPropertyMarginRight:
2273         return paddingOrMarginIsRendererDependent<&RenderStyle::marginRight>(style, renderer);
2274     case CSSPropertyMarginBottom:
2275         return paddingOrMarginIsRendererDependent<&RenderStyle::marginBottom>(style, renderer);
2276     case CSSPropertyMarginLeft:
2277         return paddingOrMarginIsRendererDependent<&RenderStyle::marginLeft>(style, renderer);
2278     case CSSPropertyPadding: {
2279         if (!renderer || !renderer->isBox())
2280             return false;
2281         return !(style && style->paddingTop().isFixed() && style->paddingRight().isFixed()
2282             && style->paddingBottom().isFixed() && style->paddingLeft().isFixed());
2283     }
2284     case CSSPropertyPaddingTop:
2285         return paddingOrMarginIsRendererDependent<&RenderStyle::paddingTop>(style, renderer);
2286     case CSSPropertyPaddingRight:
2287         return paddingOrMarginIsRendererDependent<&RenderStyle::paddingRight>(style, renderer);
2288     case CSSPropertyPaddingBottom:
2289         return paddingOrMarginIsRendererDependent<&RenderStyle::paddingBottom>(style, renderer);
2290     case CSSPropertyPaddingLeft:
2291         return paddingOrMarginIsRendererDependent<&RenderStyle::paddingLeft>(style, renderer); 
2292     case CSSPropertyGridTemplateColumns:
2293     case CSSPropertyGridTemplateRows:
2294     case CSSPropertyGridTemplate:
2295     case CSSPropertyGrid:
2296         return renderer && renderer->isRenderGrid();
2297     default:
2298         return false;
2299     }
2300 }
2301
2302 Element* ComputedStyleExtractor::styledElement()
2303 {
2304     if (!m_element)
2305         return nullptr;
2306     PseudoElement* pseudoElement;
2307     if (m_pseudoElementSpecifier == BEFORE && (pseudoElement = m_element->beforePseudoElement()))
2308         return pseudoElement;
2309     if (m_pseudoElementSpecifier == AFTER && (pseudoElement = m_element->afterPseudoElement()))
2310         return pseudoElement;
2311     return m_element.get();
2312 }
2313
2314 static StyleSelfAlignmentData resolveLegacyJustifyItems(const StyleSelfAlignmentData& data)
2315 {
2316     if (data.positionType() == LegacyPosition)
2317         return { data.position(), OverflowAlignmentDefault };
2318     return data;
2319 }
2320
2321 static StyleSelfAlignmentData resolveJustifyItemsAuto(const StyleSelfAlignmentData& data, Node* parent)
2322 {
2323     if (data.position() != ItemPositionAuto)
2324         return data;
2325
2326     // If the inherited value of justify-items includes the 'legacy' keyword, 'auto' computes to the inherited value.
2327     const auto& inheritedValue = (!parent || !parent->computedStyle()) ? RenderStyle::initialDefaultAlignment() : parent->computedStyle()->justifyItems();
2328     if (inheritedValue.positionType() == LegacyPosition)
2329         return inheritedValue;
2330     if (inheritedValue.position() == ItemPositionAuto)
2331         return resolveJustifyItemsAuto(inheritedValue, parent->parentNode());
2332     return { ItemPositionNormal, OverflowAlignmentDefault };
2333 }
2334
2335 static StyleSelfAlignmentData resolveJustifySelfAuto(const StyleSelfAlignmentData& data, Node* parent)
2336 {
2337     if (data.position() != ItemPositionAuto)
2338         return data;
2339
2340     // The 'auto' keyword computes to the computed value of justify-items on the parent or 'normal' if the box has no parent.
2341     if (!parent || !parent->computedStyle())
2342         return { ItemPositionNormal, OverflowAlignmentDefault };
2343     return resolveLegacyJustifyItems(resolveJustifyItemsAuto(parent->computedStyle()->justifyItems(), parent->parentNode()));
2344 }
2345
2346 static StyleSelfAlignmentData resolveAlignSelfAuto(const StyleSelfAlignmentData& data, Node* parent)
2347 {
2348     if (data.position() != ItemPositionAuto)
2349         return data;
2350
2351     // The 'auto' keyword computes to the computed value of align-items on the parent or 'normal' if the box has no parent.
2352     if (!parent || !parent->computedStyle())
2353         return { ItemPositionNormal, OverflowAlignmentDefault };
2354     return parent->computedStyle()->alignItems();
2355 }
2356
2357 static bool isImplicitlyInheritedGridOrFlexProperty(CSSPropertyID propertyID)
2358 {
2359     // It would be nice if grid and flex worked within normal CSS mechanisms and not invented their own inheritance system.
2360     switch (propertyID) {
2361     case CSSPropertyAlignSelf:
2362     case CSSPropertyJustifySelf:
2363     case CSSPropertyJustifyItems:
2364     // FIXME: In StyleResolver::adjustRenderStyle z-index is adjusted based on the parent display property for grid/flex.
2365     case CSSPropertyZIndex:
2366         return true;
2367     default:
2368         return false;
2369     }
2370 }
2371
2372 RefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropertyID propertyID, EUpdateLayout updateLayout) const
2373 {
2374     return ComputedStyleExtractor(m_element.ptr(), m_allowVisitedStyle, m_pseudoElementSpecifier).propertyValue(propertyID, updateLayout);
2375 }
2376
2377 Ref<MutableStyleProperties> CSSComputedStyleDeclaration::copyProperties() const
2378 {
2379     return ComputedStyleExtractor(m_element.ptr(), m_allowVisitedStyle, m_pseudoElementSpecifier).copyProperties();
2380 }
2381
2382 static inline bool hasValidStyleForProperty(Element& element, CSSPropertyID propertyID)
2383 {
2384     if (element.styleValidity() != Style::Validity::Valid)
2385         return false;
2386     if (element.document().hasPendingForcedStyleRecalc())
2387         return false;
2388     if (!element.document().childNeedsStyleRecalc())
2389         return true;
2390
2391     bool isInherited = CSSProperty::isInheritedProperty(propertyID) || isImplicitlyInheritedGridOrFlexProperty(propertyID);
2392     bool maybeExplicitlyInherited = !isInherited;
2393
2394     const auto* currentElement = &element;
2395     for (auto& ancestor : composedTreeAncestors(element)) {
2396         if (ancestor.styleValidity() >= Style::Validity::SubtreeInvalid)
2397             return false;
2398
2399         if (maybeExplicitlyInherited) {
2400             auto* style = currentElement->renderStyle();
2401             maybeExplicitlyInherited = !style || style->hasExplicitlyInheritedProperties();
2402         }
2403
2404         if ((isInherited || maybeExplicitlyInherited) && ancestor.styleValidity() == Style::Validity::ElementInvalid)
2405             return false;
2406
2407         if (ancestor.directChildNeedsStyleRecalc() && currentElement->styleIsAffectedByPreviousSibling())
2408             return false;
2409
2410         currentElement = &ancestor;
2411     }
2412
2413     return true;
2414 }
2415
2416 static bool updateStyleIfNeededForProperty(Element& element, CSSPropertyID propertyID)
2417 {
2418     auto& document = element.document();
2419
2420     document.styleScope().flushPendingUpdate();
2421
2422     if (hasValidStyleForProperty(element, propertyID))
2423         return false;
2424
2425     document.updateStyleIfNeeded();
2426     return true;
2427 }
2428
2429 static inline const RenderStyle* computeRenderStyleForProperty(Element& element, PseudoId pseudoElementSpecifier, CSSPropertyID propertyID, std::unique_ptr<RenderStyle>& ownedStyle)
2430 {
2431     auto* renderer = element.renderer();
2432
2433     if (renderer && renderer->isComposited() && CSSAnimationController::supportsAcceleratedAnimationOfProperty(propertyID)) {
2434         ownedStyle = renderer->animation().getAnimatedStyleForRenderer(*renderer);
2435         if (pseudoElementSpecifier && !element.isPseudoElement()) {
2436             // FIXME: This cached pseudo style will only exist if the animation has been run at least once.
2437             return ownedStyle->getCachedPseudoStyle(pseudoElementSpecifier);
2438         }
2439         return ownedStyle.get();
2440     }
2441
2442     return element.computedStyle(element.isPseudoElement() ? NOPSEUDO : pseudoElementSpecifier);
2443 }
2444
2445 static Ref<CSSValue> shapePropertyValue(const RenderStyle& style, const ShapeValue* shapeValue)
2446 {
2447     if (!shapeValue)
2448         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
2449
2450     if (shapeValue->type() == ShapeValue::Type::Box)
2451         return CSSValuePool::singleton().createValue(shapeValue->cssBox());
2452
2453     if (shapeValue->type() == ShapeValue::Type::Image) {
2454         if (shapeValue->image())
2455             return shapeValue->image()->cssValue();
2456         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
2457     }
2458
2459     ASSERT(shapeValue->type() == ShapeValue::Type::Shape);
2460
2461     auto list = CSSValueList::createSpaceSeparated();
2462     list->append(valueForBasicShape(style, *shapeValue->shape()));
2463     if (shapeValue->cssBox() != BoxMissing)
2464         list->append(CSSValuePool::singleton().createValue(shapeValue->cssBox()));
2465     return WTFMove(list);
2466 }
2467
2468 static Ref<CSSValueList> valueForItemPositionWithOverflowAlignment(const StyleSelfAlignmentData& data)
2469 {
2470     auto& cssValuePool = CSSValuePool::singleton();
2471     auto result = CSSValueList::createSpaceSeparated();
2472     if (data.positionType() == LegacyPosition)
2473         result->append(cssValuePool.createIdentifierValue(CSSValueLegacy));
2474     if (data.position() == ItemPositionBaseline)
2475         result->append(cssValuePool.createIdentifierValue(CSSValueBaseline));
2476     else if (data.position() == ItemPositionLastBaseline) {
2477         result->append(cssValuePool.createIdentifierValue(CSSValueLast));
2478         result->append(cssValuePool.createIdentifierValue(CSSValueBaseline));
2479     } else
2480         result->append(cssValuePool.createValue(data.position()));
2481     if (data.position() >= ItemPositionCenter && data.overflow() != OverflowAlignmentDefault)
2482         result->append(cssValuePool.createValue(data.overflow()));
2483     ASSERT(result->length() <= 2);
2484     return result;
2485 }
2486
2487 static Ref<CSSValueList> valueForContentPositionAndDistributionWithOverflowAlignment(const StyleContentAlignmentData& data, CSSValueID normalBehaviorValueID)
2488 {
2489     auto& cssValuePool = CSSValuePool::singleton();
2490     auto result = CSSValueList::createSpaceSeparated();
2491     // Handle content-distribution values
2492     if (data.distribution() != ContentDistributionDefault)
2493         result->append(cssValuePool.createValue(data.distribution()));
2494
2495     bool gridEnabled = false;
2496     gridEnabled = RuntimeEnabledFeatures::sharedFeatures().isCSSGridLayoutEnabled();
2497
2498     // Handle content-position values (either as fallback or actual value)
2499     switch (data.position()) {
2500     case ContentPositionNormal:
2501         // Handle 'normal' value, not valid as content-distribution fallback.
2502         if (data.distribution() == ContentDistributionDefault)
2503             result->append(cssValuePool.createIdentifierValue(gridEnabled ? CSSValueNormal : normalBehaviorValueID));
2504         break;
2505     case ContentPositionLastBaseline:
2506         result->append(cssValuePool.createIdentifierValue(CSSValueLast));
2507         result->append(cssValuePool.createIdentifierValue(CSSValueBaseline));
2508         break;
2509     default:
2510         result->append(cssValuePool.createValue(data.position()));
2511     }
2512
2513     // Handle overflow-alignment (only allowed for content-position values)
2514     if ((data.position() >= ContentPositionCenter || data.distribution() != ContentDistributionDefault) && data.overflow() != OverflowAlignmentDefault)
2515         result->append(cssValuePool.createValue(data.overflow()));
2516     ASSERT(result->length() > 0);
2517     ASSERT(result->length() <= 3);
2518     return result;
2519 }
2520
2521 static Ref<CSSValue> paintOrder(PaintOrder paintOrder)
2522 {
2523     if (paintOrder == PaintOrder::Normal)
2524         return CSSPrimitiveValue::createIdentifier(CSSValueNormal);
2525     
2526     auto paintOrderList = CSSValueList::createSpaceSeparated();
2527     switch (paintOrder) {
2528     case PaintOrder::Normal:
2529         ASSERT_NOT_REACHED();
2530         break;
2531     case PaintOrder::Fill:
2532         paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueFill));
2533         break;
2534     case PaintOrder::FillMarkers:
2535         paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueFill));
2536         paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueMarkers));
2537         break;
2538     case PaintOrder::Stroke:
2539         paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueStroke));
2540         break;
2541     case PaintOrder::StrokeMarkers:
2542         paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueStroke));
2543         paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueMarkers));
2544         break;
2545     case PaintOrder::Markers:
2546         paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueMarkers));
2547         break;
2548     case PaintOrder::MarkersStroke:
2549         paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueMarkers));
2550         paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueStroke));
2551         break;
2552     }
2553     return WTFMove(paintOrderList);
2554 }
2555
2556 inline static bool isFlexOrGrid(ContainerNode* element)
2557 {
2558     return element && element->computedStyle() && element->computedStyle()->isDisplayFlexibleOrGridBox();
2559 }
2560
2561 RefPtr<CSSValue> ComputedStyleExtractor::customPropertyValue(const String& propertyName)
2562 {
2563     Element* styledElement = this->styledElement();
2564     if (!styledElement)
2565         return nullptr;
2566     
2567     if (updateStyleIfNeededForProperty(*styledElement, CSSPropertyCustom)) {
2568         // Style update may change styledElement() to PseudoElement or back.
2569         styledElement = this->styledElement();
2570     }
2571
2572     std::unique_ptr<RenderStyle> ownedStyle;
2573     auto* style = computeRenderStyleForProperty(*styledElement, m_pseudoElementSpecifier, CSSPropertyCustom, ownedStyle);
2574     if (!style)
2575         return nullptr;
2576
2577     return style->customProperties().get(propertyName);
2578 }
2579
2580 String ComputedStyleExtractor::customPropertyText(const String& propertyName)
2581 {
2582     RefPtr<CSSValue> propertyValue = customPropertyValue(propertyName);
2583     return propertyValue ? propertyValue->cssText() : emptyString();
2584 }
2585
2586 static Ref<CSSFontValue> fontShorthandValueForSelectionProperties(const FontDescription& fontDescription)
2587 {
2588     auto computedFont = CSSFontValue::create();
2589
2590     auto variantCaps = fontDescription.variantCaps();
2591     if (variantCaps == FontVariantCaps::Small)
2592         computedFont->variant = CSSValuePool::singleton().createIdentifierValue(CSSValueSmallCaps);
2593     else if (variantCaps == FontVariantCaps::Normal)
2594         computedFont->variant = CSSValuePool::singleton().createIdentifierValue(CSSValueNormal);
2595     else
2596         return CSSFontValue::create();
2597
2598     auto weight = fontDescription.weight();
2599     if (auto value = fontWeightKeyword(weight))
2600         computedFont->weight = CSSValuePool::singleton().createIdentifierValue(value.value());
2601     else if (isCSS21Weight(weight))
2602         computedFont->weight = CSSValuePool::singleton().createValue(static_cast<float>(weight), CSSPrimitiveValue::CSS_NUMBER);
2603     else
2604         return CSSFontValue::create();
2605
2606     if (auto keyword = fontStretchKeyword(fontDescription.stretch()))
2607         computedFont->stretch = CSSValuePool::singleton().createIdentifierValue(keyword.value());
2608     else
2609         return CSSFontValue::create();
2610
2611     if (auto italic = fontStyleKeyword(fontDescription.italic()))
2612         computedFont->style = CSSFontStyleValue::create(CSSValuePool::singleton().createIdentifierValue(italic.value()));
2613     else
2614         return CSSFontValue::create();
2615
2616     return computedFont;
2617 }
2618
2619 RefPtr<CSSValue> ComputedStyleExtractor::propertyValue(CSSPropertyID propertyID, EUpdateLayout updateLayout)
2620 {
2621     auto* styledElement = this->styledElement();
2622     if (!styledElement)
2623         return nullptr;
2624
2625     std::unique_ptr<RenderStyle> ownedStyle;
2626     const RenderStyle* style = nullptr;
2627     RenderObject* renderer = nullptr;
2628     bool forceFullLayout = false;
2629     if (updateLayout) {
2630         Document& document = m_element->document();
2631
2632         if (updateStyleIfNeededForProperty(*styledElement, propertyID)) {
2633             // Style update may change styledElement() to PseudoElement or back.
2634             styledElement = this->styledElement();
2635         }
2636         renderer = styledElement->renderer();
2637
2638         if (propertyID == CSSPropertyDisplay && !renderer && is<SVGElement>(*styledElement) && !downcast<SVGElement>(*styledElement).isValid())
2639             return nullptr;
2640
2641         style = computeRenderStyleForProperty(*styledElement, m_pseudoElementSpecifier, propertyID, ownedStyle);
2642
2643         // FIXME: Some of these cases could be narrowed down or optimized better.
2644         forceFullLayout = isLayoutDependent(propertyID, style, renderer)
2645             || styledElement->isInShadowTree()
2646             || (document.styleScope().resolverIfExists() && document.styleScope().resolverIfExists()->hasViewportDependentMediaQueries() && document.ownerElement());
2647
2648         if (forceFullLayout) {
2649             document.updateLayoutIgnorePendingStylesheets();
2650             styledElement = this->styledElement();
2651         }
2652     }
2653
2654     if (!updateLayout || forceFullLayout) {
2655         style = computeRenderStyleForProperty(*styledElement, m_pseudoElementSpecifier, propertyID, ownedStyle);
2656         renderer = styledElement->renderer();
2657     }
2658
2659     if (!style)
2660         return nullptr;
2661
2662     auto& cssValuePool = CSSValuePool::singleton();
2663     propertyID = CSSProperty::resolveDirectionAwareProperty(propertyID, style->direction(), style->writingMode());
2664
2665     switch (propertyID) {
2666         case CSSPropertyInvalid:
2667             break;
2668
2669         case CSSPropertyBackgroundColor:
2670             return cssValuePool.createColorValue(m_allowVisitedStyle? style->visitedDependentColor(CSSPropertyBackgroundColor) : style->backgroundColor());
2671         case CSSPropertyBackgroundImage:
2672         case CSSPropertyWebkitMaskImage: {
2673             auto& layers = propertyID == CSSPropertyWebkitMaskImage ? style->maskLayers() : style->backgroundLayers();
2674             if (!layers.next()) {
2675                 if (layers.image())
2676                     return layers.image()->cssValue();
2677                 return cssValuePool.createIdentifierValue(CSSValueNone);
2678             }
2679             auto list = CSSValueList::createCommaSeparated();
2680             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next()) {
2681                 if (currLayer->image())
2682                     list->append(currLayer->image()->cssValue());
2683                 else
2684                     list->append(cssValuePool.createIdentifierValue(CSSValueNone));
2685             }
2686             return WTFMove(list);
2687         }
2688         case CSSPropertyBackgroundSize:
2689         case CSSPropertyWebkitBackgroundSize:
2690         case CSSPropertyWebkitMaskSize: {
2691             auto& layers = propertyID == CSSPropertyWebkitMaskSize ? style->maskLayers() : style->backgroundLayers();
2692             if (!layers.next())
2693                 return fillSizeToCSSValue(layers.size(), *style);
2694             auto list = CSSValueList::createCommaSeparated();
2695             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2696                 list->append(fillSizeToCSSValue(currLayer->size(), *style));
2697             return WTFMove(list);
2698         }
2699         case CSSPropertyBackgroundRepeat:
2700         case CSSPropertyWebkitMaskRepeat: {
2701             auto& layers = propertyID == CSSPropertyWebkitMaskRepeat ? style->maskLayers() : style->backgroundLayers();
2702             if (!layers.next())
2703                 return fillRepeatToCSSValue(layers.repeatX(), layers.repeatY());
2704             auto list = CSSValueList::createCommaSeparated();
2705             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2706                 list->append(fillRepeatToCSSValue(currLayer->repeatX(), currLayer->repeatY()));
2707             return WTFMove(list);
2708         }
2709         case CSSPropertyWebkitMaskSourceType: {
2710             auto& layers = style->maskLayers();
2711             if (!layers.next())
2712                 return fillSourceTypeToCSSValue(layers.maskSourceType());
2713             auto list = CSSValueList::createCommaSeparated();
2714             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2715                 list->append(fillSourceTypeToCSSValue(currLayer->maskSourceType()));
2716             return WTFMove(list);
2717         }
2718         case CSSPropertyWebkitBackgroundComposite:
2719         case CSSPropertyWebkitMaskComposite: {
2720             auto& layers = propertyID == CSSPropertyWebkitMaskComposite ? style->maskLayers() : style->backgroundLayers();
2721             if (!layers.next())
2722                 return cssValuePool.createValue(layers.composite());
2723             auto list = CSSValueList::createCommaSeparated();
2724             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2725                 list->append(cssValuePool.createValue(currLayer->composite()));
2726             return WTFMove(list);
2727         }
2728         case CSSPropertyBackgroundAttachment: {
2729             auto& layers = style->backgroundLayers();
2730             if (!layers.next())
2731                 return cssValuePool.createValue(layers.attachment());
2732             auto list = CSSValueList::createCommaSeparated();
2733             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2734                 list->append(cssValuePool.createValue(currLayer->attachment()));
2735             return WTFMove(list);
2736         }
2737         case CSSPropertyBackgroundClip:
2738         case CSSPropertyBackgroundOrigin:
2739         case CSSPropertyWebkitBackgroundClip:
2740         case CSSPropertyWebkitBackgroundOrigin:
2741         case CSSPropertyWebkitMaskClip:
2742         case CSSPropertyWebkitMaskOrigin: {
2743             auto& layers = (propertyID == CSSPropertyWebkitMaskClip || propertyID == CSSPropertyWebkitMaskOrigin) ? style->maskLayers() : style->backgroundLayers();
2744             bool isClip = propertyID == CSSPropertyBackgroundClip || propertyID == CSSPropertyWebkitBackgroundClip || propertyID == CSSPropertyWebkitMaskClip;
2745             if (!layers.next())
2746                 return cssValuePool.createValue(isClip ? layers.clip() : layers.origin());
2747             auto list = CSSValueList::createCommaSeparated();
2748             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2749                 list->append(cssValuePool.createValue(isClip ? currLayer->clip() : currLayer->origin()));
2750             return WTFMove(list);
2751         }
2752         case CSSPropertyBackgroundPosition:
2753         case CSSPropertyWebkitMaskPosition: {
2754             auto& layers = propertyID == CSSPropertyWebkitMaskPosition ? style->maskLayers() : style->backgroundLayers();
2755             if (!layers.next())
2756                 return createPositionListForLayer(propertyID, layers, *style);
2757
2758             auto list = CSSValueList::createCommaSeparated();
2759             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2760                 list->append(createPositionListForLayer(propertyID, *currLayer, *style));
2761             return WTFMove(list);
2762         }
2763         case CSSPropertyBackgroundPositionX:
2764         case CSSPropertyWebkitMaskPositionX: {
2765             auto& layers = propertyID == CSSPropertyWebkitMaskPositionX ? style->maskLayers() : style->backgroundLayers();
2766             if (!layers.next())
2767                 return cssValuePool.createValue(layers.xPosition());
2768
2769             auto list = CSSValueList::createCommaSeparated();
2770             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2771                 list->append(cssValuePool.createValue(currLayer->xPosition()));
2772
2773             return WTFMove(list);
2774         }
2775         case CSSPropertyBackgroundPositionY:
2776         case CSSPropertyWebkitMaskPositionY: {
2777             auto& layers = propertyID == CSSPropertyWebkitMaskPositionY ? style->maskLayers() : style->backgroundLayers();
2778             if (!layers.next())
2779                 return cssValuePool.createValue(layers.yPosition());
2780
2781             auto list = CSSValueList::createCommaSeparated();
2782             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2783                 list->append(cssValuePool.createValue(currLayer->yPosition()));
2784
2785             return WTFMove(list);
2786         }
2787         case CSSPropertyBorderCollapse:
2788             if (style->borderCollapse())
2789                 return cssValuePool.createIdentifierValue(CSSValueCollapse);
2790             return cssValuePool.createIdentifierValue(CSSValueSeparate);
2791         case CSSPropertyBorderSpacing: {
2792             auto list = CSSValueList::createSpaceSeparated();
2793             list->append(zoomAdjustedPixelValue(style->horizontalBorderSpacing(), *style));
2794             list->append(zoomAdjustedPixelValue(style->verticalBorderSpacing(), *style));
2795             return WTFMove(list);
2796         }
2797         case CSSPropertyWebkitBorderHorizontalSpacing:
2798             return zoomAdjustedPixelValue(style->horizontalBorderSpacing(), *style);
2799         case CSSPropertyWebkitBorderVerticalSpacing:
2800             return zoomAdjustedPixelValue(style->verticalBorderSpacing(), *style);
2801         case CSSPropertyBorderImageSource:
2802             if (style->borderImageSource())
2803                 return style->borderImageSource()->cssValue();
2804             return cssValuePool.createIdentifierValue(CSSValueNone);
2805         case CSSPropertyBorderTopColor:
2806             return m_allowVisitedStyle ? cssValuePool.createColorValue(style->visitedDependentColor(CSSPropertyBorderTopColor)) : currentColorOrValidColor(style, style->borderTopColor());
2807         case CSSPropertyBorderRightColor:
2808             return m_allowVisitedStyle ? cssValuePool.createColorValue(style->visitedDependentColor(CSSPropertyBorderRightColor)) : currentColorOrValidColor(style, style->borderRightColor());
2809         case CSSPropertyBorderBottomColor:
2810             return m_allowVisitedStyle ? cssValuePool.createColorValue(style->visitedDependentColor(CSSPropertyBorderBottomColor)) : currentColorOrValidColor(style, style->borderBottomColor());
2811         case CSSPropertyBorderLeftColor:
2812             return m_allowVisitedStyle ? cssValuePool.createColorValue(style->visitedDependentColor(CSSPropertyBorderLeftColor)) : currentColorOrValidColor(style, style->borderLeftColor());
2813         case CSSPropertyBorderTopStyle:
2814             return cssValuePool.createValue(style->borderTopStyle());
2815         case CSSPropertyBorderRightStyle:
2816             return cssValuePool.createValue(style->borderRightStyle());
2817         case CSSPropertyBorderBottomStyle:
2818             return cssValuePool.createValue(style->borderBottomStyle());
2819         case CSSPropertyBorderLeftStyle:
2820             return cssValuePool.createValue(style->borderLeftStyle());
2821         case CSSPropertyBorderTopWidth:
2822             return zoomAdjustedPixelValue(style->borderTopWidth(), *style);
2823         case CSSPropertyBorderRightWidth:
2824             return zoomAdjustedPixelValue(style->borderRightWidth(), *style);
2825         case CSSPropertyBorderBottomWidth:
2826             return zoomAdjustedPixelValue(style->borderBottomWidth(), *style);
2827         case CSSPropertyBorderLeftWidth:
2828             return zoomAdjustedPixelValue(style->borderLeftWidth(), *style);
2829         case CSSPropertyBottom:
2830             return positionOffsetValue(*style, CSSPropertyBottom);
2831         case CSSPropertyWebkitBoxAlign:
2832             return cssValuePool.createValue(style->boxAlign());
2833 #if ENABLE(CSS_BOX_DECORATION_BREAK)
2834         case CSSPropertyWebkitBoxDecorationBreak:
2835             if (style->boxDecorationBreak() == DSLICE)
2836                 return cssValuePool.createIdentifierValue(CSSValueSlice);
2837         return cssValuePool.createIdentifierValue(CSSValueClone);
2838 #endif
2839         case CSSPropertyWebkitBoxDirection:
2840             return cssValuePool.createValue(style->boxDirection());
2841         case CSSPropertyWebkitBoxFlex:
2842             return cssValuePool.createValue(style->boxFlex(), CSSPrimitiveValue::CSS_NUMBER);
2843         case CSSPropertyWebkitBoxFlexGroup:
2844             return cssValuePool.createValue(style->boxFlexGroup(), CSSPrimitiveValue::CSS_NUMBER);
2845         case CSSPropertyWebkitBoxLines:
2846             return cssValuePool.createValue(style->boxLines());
2847         case CSSPropertyWebkitBoxOrdinalGroup:
2848             return cssValuePool.createValue(style->boxOrdinalGroup(), CSSPrimitiveValue::CSS_NUMBER);
2849         case CSSPropertyWebkitBoxOrient:
2850             return cssValuePool.createValue(style->boxOrient());
2851         case CSSPropertyWebkitBoxPack:
2852             return cssValuePool.createValue(style->boxPack());
2853         case CSSPropertyWebkitBoxReflect:
2854             return valueForReflection(style->boxReflect(), *style);
2855         case CSSPropertyBoxShadow:
2856         case CSSPropertyWebkitBoxShadow:
2857             return valueForShadow(style->boxShadow(), propertyID, *style);
2858         case CSSPropertyCaptionSide:
2859             return cssValuePool.createValue(style->captionSide());
2860         case CSSPropertyClear:
2861             return cssValuePool.createValue(style->clear());
2862         case CSSPropertyColor:
2863             return cssValuePool.createColorValue(m_allowVisitedStyle ? style->visitedDependentColor(CSSPropertyColor) : style->color());
2864         case CSSPropertyWebkitPrintColorAdjust:
2865             return cssValuePool.createValue(style->printColorAdjust());
2866         case CSSPropertyWebkitColumnAxis:
2867             return cssValuePool.createValue(style->columnAxis());
2868         case CSSPropertyColumnCount:
2869             if (style->hasAutoColumnCount())
2870                 return cssValuePool.createIdentifierValue(CSSValueAuto);
2871             return cssValuePool.createValue(style->columnCount(), CSSPrimitiveValue::CSS_NUMBER);
2872         case CSSPropertyColumnFill:
2873             return cssValuePool.createValue(style->columnFill());
2874         case CSSPropertyColumnGap:
2875             if (style->hasNormalColumnGap())
2876                 return cssValuePool.createIdentifierValue(CSSValueNormal);
2877             return zoomAdjustedPixelValue(style->columnGap(), *style);
2878         case CSSPropertyWebkitColumnProgression:
2879             return cssValuePool.createValue(style->columnProgression());
2880         case CSSPropertyColumnRuleColor:
2881             return m_allowVisitedStyle ? cssValuePool.createColorValue(style->visitedDependentColor(CSSPropertyOutlineColor)) : currentColorOrValidColor(style, style->columnRuleColor());
2882         case CSSPropertyColumnRuleStyle:
2883             return cssValuePool.createValue(style->columnRuleStyle());
2884         case CSSPropertyColumnRuleWidth:
2885             return zoomAdjustedPixelValue(style->columnRuleWidth(), *style);
2886         case CSSPropertyColumnSpan:
2887             return cssValuePool.createIdentifierValue(style->columnSpan() ? CSSValueAll : CSSValueNone);
2888         case CSSPropertyWebkitColumnBreakAfter:
2889             return cssValuePool.createValue(convertToColumnBreak(style->breakAfter()));
2890         case CSSPropertyWebkitColumnBreakBefore:
2891             return cssValuePool.createValue(convertToColumnBreak(style->breakBefore()));
2892         case CSSPropertyWebkitColumnBreakInside:
2893             return cssValuePool.createValue(convertToColumnBreak(style->breakInside()));
2894         case CSSPropertyColumnWidth:
2895             if (style->hasAutoColumnWidth())
2896                 return cssValuePool.createIdentifierValue(CSSValueAuto);
2897             return zoomAdjustedPixelValue(style->columnWidth(), *style);
2898         case CSSPropertyTabSize:
2899             return cssValuePool.createValue(style->tabSize(), CSSPrimitiveValue::CSS_NUMBER);
2900 #if ENABLE(CSS_REGIONS)
2901         case CSSPropertyWebkitRegionBreakAfter:
2902             return cssValuePool.createValue(convertToRegionBreak(style->breakAfter()));
2903         case CSSPropertyWebkitRegionBreakBefore:
2904             return cssValuePool.createValue(convertToRegionBreak(style->breakBefore()));
2905         case CSSPropertyWebkitRegionBreakInside:
2906             return cssValuePool.createValue(convertToRegionBreak(style->breakInside()));
2907 #endif
2908         case CSSPropertyCursor: {
2909             RefPtr<CSSValueList> list;
2910             auto* cursors = style->cursors();
2911             if (cursors && cursors->size() > 0) {
2912                 list = CSSValueList::createCommaSeparated();
2913                 for (unsigned i = 0; i < cursors->size(); ++i)
2914                     if (StyleImage* image = cursors->at(i).image())
2915                         list->append(image->cssValue());
2916             }
2917             auto value = cssValuePool.createValue(style->cursor());
2918             if (list) {
2919                 list->append(WTFMove(value));
2920                 return list;
2921             }
2922             return WTFMove(value);
2923         }
2924 #if ENABLE(CURSOR_VISIBILITY)
2925         case CSSPropertyWebkitCursorVisibility:
2926             return cssValuePool.createValue(style->cursorVisibility());
2927 #endif
2928         case CSSPropertyDirection:
2929             return cssValuePool.createValue(style->direction());
2930         case CSSPropertyDisplay:
2931             return cssValuePool.createValue(style->display());
2932         case CSSPropertyEmptyCells:
2933             return cssValuePool.createValue(style->emptyCells());
2934         case CSSPropertyAlignContent:
2935             return valueForContentPositionAndDistributionWithOverflowAlignment(style->alignContent(), CSSValueStretch);
2936         case CSSPropertyAlignItems:
2937             return valueForItemPositionWithOverflowAlignment(style->alignItems());
2938         case CSSPropertyAlignSelf:
2939             return valueForItemPositionWithOverflowAlignment(resolveAlignSelfAuto(style->alignSelf(), styledElement->parentNode()));
2940         case CSSPropertyFlex:
2941             return getCSSPropertyValuesForShorthandProperties(flexShorthand());
2942         case CSSPropertyFlexBasis:
2943             return cssValuePool.createValue(style->flexBasis(), *style);
2944         case CSSPropertyFlexDirection:
2945             return cssValuePool.createValue(style->flexDirection());
2946         case CSSPropertyFlexFlow:
2947             return getCSSPropertyValuesForShorthandProperties(flexFlowShorthand());
2948         case CSSPropertyFlexGrow:
2949             return cssValuePool.createValue(style->flexGrow());
2950         case CSSPropertyFlexShrink:
2951             return cssValuePool.createValue(style->flexShrink());
2952         case CSSPropertyFlexWrap:
2953             return cssValuePool.createValue(style->flexWrap());
2954         case CSSPropertyJustifyContent:
2955             return valueForContentPositionAndDistributionWithOverflowAlignment(style->justifyContent(), CSSValueFlexStart);
2956         case CSSPropertyJustifyItems:
2957             return valueForItemPositionWithOverflowAlignment(resolveJustifyItemsAuto(style->justifyItems(), styledElement->parentNode()));
2958         case CSSPropertyJustifySelf:
2959             return valueForItemPositionWithOverflowAlignment(resolveJustifySelfAuto(style->justifySelf(), styledElement->parentNode()));
2960         case CSSPropertyPlaceContent:
2961             return getCSSPropertyValuesForShorthandProperties(placeContentShorthand());
2962         case CSSPropertyPlaceItems:
2963             return getCSSPropertyValuesForShorthandProperties(placeItemsShorthand());
2964         case CSSPropertyOrder:
2965             return cssValuePool.createValue(style->order(), CSSPrimitiveValue::CSS_NUMBER);
2966         case CSSPropertyFloat:
2967             if (style->display() != NONE && style->hasOutOfFlowPosition())
2968                 return cssValuePool.createIdentifierValue(CSSValueNone);
2969             return cssValuePool.createValue(style->floating());
2970         case CSSPropertyFont: {
2971             auto computedFont = fontShorthandValueForSelectionProperties(style->fontDescription());
2972             computedFont->size = fontSizeFromStyle(*style);
2973             computedFont->lineHeight = lineHeightFromStyle(*style);
2974             computedFont->family = fontFamilyListFromStyle(*style);
2975             return WTFMove(computedFont);
2976         }
2977         case CSSPropertyFontFamily:
2978             return fontFamilyFromStyle(*style);
2979         case CSSPropertyFontSize:
2980             return fontSizeFromStyle(*style);
2981         case CSSPropertyFontStyle:
2982             return fontStyleFromStyle(*style);
2983         case CSSPropertyFontStretch:
2984             return fontStretchFromStyle(*style);
2985         case CSSPropertyFontVariant:
2986             return fontVariantFromStyle(*style);
2987         case CSSPropertyFontWeight:
2988             return fontWeightFromStyle(*style);
2989         case CSSPropertyFontSynthesis:
2990             return fontSynthesisFromStyle(*style);
2991         case CSSPropertyFontFeatureSettings: {
2992             const FontFeatureSettings& featureSettings = style->fontDescription().featureSettings();
2993             if (!featureSettings.size())
2994                 return cssValuePool.createIdentifierValue(CSSValueNormal);
2995             auto list = CSSValueList::createCommaSeparated();
2996             for (auto& feature : featureSettings)
2997                 list->append(CSSFontFeatureValue::create(FontTag(feature.tag()), feature.value()));
2998             return WTFMove(list);
2999         }
3000 #if ENABLE(VARIATION_FONTS)
3001         case CSSPropertyFontVariationSettings: {
3002             const FontVariationSettings& variationSettings = style->fontDescription().variationSettings();
3003             if (variationSettings.isEmpty())
3004                 return cssValuePool.createIdentifierValue(CSSValueNormal);
3005             auto list = CSSValueList::createCommaSeparated();
3006             for (auto& feature : variationSettings)
3007                 list->append(CSSFontVariationValue::create(feature.tag(), feature.value()));
3008             return WTFMove(list);
3009         }
3010         case CSSPropertyFontOpticalSizing:
3011             return cssValuePool.createValue(style->fontDescription().opticalSizing());
3012 #endif
3013         case CSSPropertyGridAutoFlow: {
3014             auto list = CSSValueList::createSpaceSeparated();
3015             ASSERT(style->isGridAutoFlowDirectionRow() || style->isGridAutoFlowDirectionColumn());
3016             if (style->isGridAutoFlowDirectionRow())
3017                 list->append(cssValuePool.createIdentifierValue(CSSValueRow));
3018             else
3019                 list->append(cssValuePool.createIdentifierValue(CSSValueColumn));
3020
3021             if (style->isGridAutoFlowAlgorithmDense())
3022                 list->append(cssValuePool.createIdentifierValue(CSSValueDense));
3023
3024             return WTFMove(list);
3025         }
3026
3027         // Specs mention that getComputedStyle() should return the used value of the property instead of the computed
3028         // one for grid-template-{rows|columns} but not for the grid-auto-{rows|columns} as things like
3029         // grid-auto-columns: 2fr; cannot be resolved to a value in pixels as the '2fr' means very different things
3030         // depending on the size of the explicit grid or the number of implicit tracks added to the grid. See
3031         // http://lists.w3.org/Archives/Public/www-style/2013Nov/0014.html
3032         case CSSPropertyGridAutoColumns:
3033             return valueForGridTrackSizeList(ForColumns, *style);
3034         case CSSPropertyGridAutoRows:
3035             return valueForGridTrackSizeList(ForRows, *style);
3036
3037         case CSSPropertyGridTemplateColumns:
3038             return valueForGridTrackList(ForColumns, renderer, *style);
3039         case CSSPropertyGridTemplateRows:
3040             return valueForGridTrackList(ForRows, renderer, *style);
3041
3042         case CSSPropertyGridColumnStart:
3043             return valueForGridPosition(style->gridItemColumnStart());
3044         case CSSPropertyGridColumnEnd:
3045             return valueForGridPosition(style->gridItemColumnEnd());
3046         case CSSPropertyGridRowStart:
3047             return valueForGridPosition(style->gridItemRowStart());
3048         case CSSPropertyGridRowEnd:
3049             return valueForGridPosition(style->gridItemRowEnd());
3050         case CSSPropertyGridArea:
3051             return getCSSPropertyValuesForGridShorthand(gridAreaShorthand());
3052         case CSSPropertyGridTemplate:
3053             return getCSSPropertyValuesForGridShorthand(gridTemplateShorthand());
3054         case CSSPropertyGrid:
3055             return getCSSPropertyValuesForGridShorthand(gridShorthand());
3056         case CSSPropertyGridColumn:
3057             return getCSSPropertyValuesForGridShorthand(gridColumnShorthand());
3058         case CSSPropertyGridRow:
3059             return getCSSPropertyValuesForGridShorthand(gridRowShorthand());
3060         case CSSPropertyGridTemplateAreas:
3061             if (!style->namedGridAreaRowCount()) {
3062                 ASSERT(!style->namedGridAreaColumnCount());
3063                 return cssValuePool.createIdentifierValue(CSSValueNone);
3064             }
3065             return CSSGridTemplateAreasValue::create(style->namedGridArea(), style->namedGridAreaRowCount(), style->namedGridAreaColumnCount());
3066         case CSSPropertyGridColumnGap:
3067             return zoomAdjustedPixelValueForLength(style->gridColumnGap(), *style);
3068         case CSSPropertyGridRowGap:
3069             return zoomAdjustedPixelValueForLength(style->gridRowGap(), *style);
3070         case CSSPropertyGridGap:
3071             return getCSSPropertyValuesForGridShorthand(gridGapShorthand());
3072         case CSSPropertyHeight:
3073             if (renderer && !renderer->isRenderSVGModelObject()) {
3074                 // According to http://www.w3.org/TR/CSS2/visudet.html#the-height-property,
3075                 // the "height" property does not apply for non-replaced inline elements.
3076                 if (!renderer->isReplaced() && renderer->isInline())
3077                     return cssValuePool.createIdentifierValue(CSSValueAuto);
3078                 return zoomAdjustedPixelValue(sizingBox(*renderer).height(), *style);
3079             }
3080             return zoomAdjustedPixelValueForLength(style->height(), *style);
3081         case CSSPropertyWebkitHyphens:
3082             return cssValuePool.createValue(style->hyphens());
3083         case CSSPropertyWebkitHyphenateCharacter:
3084             if (style->hyphenationString().isNull())
3085                 return cssValuePool.createIdentifierValue(CSSValueAuto);
3086             return cssValuePool.createValue(style->hyphenationString(), CSSPrimitiveValue::CSS_STRING);
3087         case CSSPropertyWebkitHyphenateLimitAfter:
3088             if (style->hyphenationLimitAfter() < 0)
3089                 return CSSPrimitiveValue::createIdentifier(CSSValueAuto);
3090             return CSSPrimitiveValue::create(style->hyphenationLimitAfter(), CSSPrimitiveValue::CSS_NUMBER);
3091         case CSSPropertyWebkitHyphenateLimitBefore:
3092             if (style->hyphenationLimitBefore() < 0)
3093                 return CSSPrimitiveValue::createIdentifier(CSSValueAuto);
3094             return CSSPrimitiveValue::create(style->hyphenationLimitBefore(), CSSPrimitiveValue::CSS_NUMBER);
3095         case CSSPropertyWebkitHyphenateLimitLines:
3096             if (style->hyphenationLimitLines() < 0)
3097                 return CSSPrimitiveValue::createIdentifier(CSSValueNoLimit);
3098             return CSSPrimitiveValue::create(style->hyphenationLimitLines(), CSSPrimitiveValue::CSS_NUMBER);
3099         case CSSPropertyWebkitBorderFit:
3100             if (style->borderFit() == BorderFitBorder)
3101                 return cssValuePool.createIdentifierValue(CSSValueBorder);
3102             return cssValuePool.createIdentifierValue(CSSValueLines);
3103 #if ENABLE(CSS_IMAGE_ORIENTATION)
3104         case CSSPropertyImageOrientation:
3105             return cssValuePool.createValue(style->imageOrientation());
3106 #endif
3107         case CSSPropertyImageRendering:
3108             return CSSPrimitiveValue::create(style->imageRendering());
3109 #if ENABLE(CSS_IMAGE_RESOLUTION)
3110         case CSSPropertyImageResolution:
3111             return cssValuePool.createValue(style->imageResolution(), CSSPrimitiveValue::CSS_DPPX);
3112 #endif
3113         case CSSPropertyLeft:
3114             return positionOffsetValue(*style, CSSPropertyLeft);
3115         case CSSPropertyLetterSpacing:
3116             if (!style->letterSpacing())
3117                 return cssValuePool.createIdentifierValue(CSSValueNormal);
3118             return zoomAdjustedPixelValue(style->letterSpacing(), *style);
3119         case CSSPropertyWebkitLineClamp:
3120             if (style->lineClamp().isNone())
3121                 return cssValuePool.createIdentifierValue(CSSValueNone);
3122             return cssValuePool.createValue(style->lineClamp().value(), style->lineClamp().isPercentage() ? CSSPrimitiveValue::CSS_PERCENTAGE : CSSPrimitiveValue::CSS_NUMBER);
3123         case CSSPropertyLineHeight:
3124             return lineHeightFromStyle(*style);
3125         case CSSPropertyListStyleImage:
3126             if (style->listStyleImage())
3127                 return style->listStyleImage()->cssValue();
3128             return cssValuePool.createIdentifierValue(CSSValueNone);
3129         case CSSPropertyListStylePosition:
3130             return cssValuePool.createValue(style->listStylePosition());
3131         case CSSPropertyListStyleType:
3132             return cssValuePool.createValue(style->listStyleType());
3133         case CSSPropertyWebkitLocale:
3134             if (style->locale().isNull())
3135                 return cssValuePool.createIdentifierValue(CSSValueAuto);
3136             return cssValuePool.createValue(style->locale(), CSSPrimitiveValue::CSS_STRING);
3137         case CSSPropertyMarginTop:
3138             return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::marginTop, &RenderBoxModelObject::marginTop>(*style, renderer);
3139         case CSSPropertyMarginRight: {
3140             Length marginRight = style->marginRight();
3141             if (marginRight.isFixed() || !is<RenderBox>(renderer))
3142                 return zoomAdjustedPixelValueForLength(marginRight, *style);
3143             float value;
3144             if (marginRight.isPercentOrCalculated()) {
3145                 // RenderBox gives a marginRight() that is the distance between the right-edge of the child box
3146                 // and the right-edge of the containing box, when display == BLOCK. Let's calculate the absolute
3147                 // value of the specified margin-right % instead of relying on RenderBox's marginRight() value.
3148                 value = minimumValueForLength(marginRight, downcast<RenderBox>(*renderer).containingBlockLogicalWidthForContent());
3149             } else
3150                 value = downcast<RenderBox>(*renderer).marginRight();
3151             return zoomAdjustedPixelValue(value, *style);
3152         }
3153         case CSSPropertyMarginBottom:
3154             return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::marginBottom, &RenderBoxModelObject::marginBottom>(*style, renderer);
3155         case CSSPropertyMarginLeft:
3156             return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::marginLeft, &RenderBoxModelObject::marginLeft>(*style, renderer);
3157         case CSSPropertyWebkitMarqueeDirection:
3158             return cssValuePool.createValue(style->marqueeDirection());
3159         case CSSPropertyWebkitMarqueeIncrement:
3160             return cssValuePool.createValue(style->marqueeIncrement());
3161         case CSSPropertyWebkitMarqueeRepetition:
3162             if (style->marqueeLoopCount() < 0)
3163                 return cssValuePool.createIdentifierValue(CSSValueInfinite);
3164             return cssValuePool.createValue(style->marqueeLoopCount(), CSSPrimitiveValue::CSS_NUMBER);
3165         case CSSPropertyWebkitMarqueeStyle:
3166             return cssValuePool.createValue(style->marqueeBehavior());
3167         case CSSPropertyWebkitUserModify:
3168             return cssValuePool.createValue(style->userModify());
3169         case CSSPropertyMaxHeight: {
3170             const Length& maxHeight = style->maxHeight();
3171             if (maxHeight.isUndefined())
3172                 return cssValuePool.createIdentifierValue(CSSValueNone);
3173             return zoomAdjustedPixelValueForLength(maxHeight, *style);
3174         }
3175         case CSSPropertyMaxWidth: {
3176             const Length& maxWidth = style->maxWidth();
3177             if (maxWidth.isUndefined())
3178                 return cssValuePool.createIdentifierValue(CSSValueNone);
3179             return zoomAdjustedPixelValueForLength(maxWidth, *style);
3180         }
3181         case CSSPropertyMinHeight:
3182             if (style->minHeight().isAuto()) {
3183                 if (isFlexOrGrid(styledElement->parentNode()))
3184                     return cssValuePool.createIdentifierValue(CSSValueAuto);
3185                 return zoomAdjustedPixelValue(0, *style);
3186             }
3187             return zoomAdjustedPixelValueForLength(style->minHeight(), *style);
3188         case CSSPropertyMinWidth:
3189             if (style->minWidth().isAuto()) {
3190                 if (isFlexOrGrid(styledElement->parentNode()))
3191                     return cssValuePool.createIdentifierValue(CSSValueAuto);
3192                 return zoomAdjustedPixelValue(0, *style);
3193             }
3194             return zoomAdjustedPixelValueForLength(style->minWidth(), *style);
3195         case CSSPropertyObjectFit:
3196             return cssValuePool.createValue(style->objectFit());
3197         case CSSPropertyObjectPosition: {
3198             auto list = CSSValueList::createSpaceSeparated();
3199             list->append(zoomAdjustedPixelValueForLength(style->objectPosition().x(), *style));
3200             list->append(zoomAdjustedPixelValueForLength(style->objectPosition().y(), *style));
3201             return WTFMove(list);
3202         }
3203         case CSSPropertyOpacity:
3204             return cssValuePool.createValue(style->opacity(), CSSPrimitiveValue::CSS_NUMBER);
3205         case CSSPropertyOrphans:
3206             if (style->hasAutoOrphans())
3207                 return cssValuePool.createIdentifierValue(CSSValueAuto);
3208             return cssValuePool.createValue(style->orphans(), CSSPrimitiveValue::CSS_NUMBER);
3209         case CSSPropertyOutlineColor:
3210             return m_allowVisitedStyle ? cssValuePool.createColorValue(style->visitedDependentColor(CSSPropertyOutlineColor)) : currentColorOrValidColor(style, style->outlineColor());
3211         case CSSPropertyOutlineOffset:
3212             return zoomAdjustedPixelValue(style->outlineOffset(), *style);
3213         case CSSPropertyOutlineStyle:
3214             if (style->outlineStyleIsAuto())
3215                 return cssValuePool.createIdentifierValue(CSSValueAuto);
3216             return cssValuePool.createValue(style->outlineStyle());
3217         case CSSPropertyOutlineWidth:
3218             return zoomAdjustedPixelValue(style->outlineWidth(), *style);
3219         case CSSPropertyOverflow:
3220             return cssValuePool.createValue(std::max(style->overflowX(), style->overflowY()));
3221         case CSSPropertyOverflowWrap:
3222             return cssValuePool.createValue(style->overflowWrap());
3223         case CSSPropertyOverflowX:
3224             return cssValuePool.createValue(style->overflowX());
3225         case CSSPropertyOverflowY:
3226             return cssValuePool.createValue(style->overflowY());
3227         case CSSPropertyPaddingTop:
3228             return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::paddingTop, &RenderBoxModelObject::computedCSSPaddingTop>(*style, renderer);
3229         case CSSPropertyPaddingRight:
3230             return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::paddingRight, &RenderBoxModelObject::computedCSSPaddingRight>(*style, renderer);
3231         case CSSPropertyPaddingBottom:
3232             return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::paddingBottom, &RenderBoxModelObject::computedCSSPaddingBottom>(*style, renderer);
3233         case CSSPropertyPaddingLeft:
3234             return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::paddingLeft, &RenderBoxModelObject::computedCSSPaddingLeft>(*style, renderer);
3235         case CSSPropertyPageBreakAfter:
3236             return cssValuePool.createValue(convertToPageBreak(style->breakAfter()));
3237         case CSSPropertyPageBreakBefore:
3238             return cssValuePool.createValue(convertToPageBreak(style->breakBefore()));
3239         case CSSPropertyPageBreakInside:
3240             return cssValuePool.createValue(convertToPageBreak(style->breakInside()));
3241         case CSSPropertyBreakAfter:
3242             return cssValuePool.createValue(style->breakAfter());
3243         case CSSPropertyBreakBefore:
3244             return cssValuePool.createValue(style->breakBefore());
3245         case CSSPropertyBreakInside:
3246             return cssValuePool.createValue(style->breakInside());
3247         case CSSPropertyHangingPunctuation:
3248             return hangingPunctuationToCSSValue(style->hangingPunctuation());
3249         case CSSPropertyPosition:
3250             return cssValuePool.createValue(style->position());
3251         case C