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