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