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