Source/WebCore/ChangeLog

 12021-05-31 Rob Buis <rbuis@igalia.com>
 2
 3 [css-contain] Support contain:style
 4 https://bugs.webkit.org/show_bug.cgi?id=226458
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 WIP.
 9
 10 * css/CSSComputedStyleDeclaration.cpp:
 11 (WebCore::ComputedStyleExtractor::valueForPropertyInStyle):
 12 * css/parser/CSSPropertyParser.cpp:
 13 (WebCore::consumeContain):
 14 * rendering/RenderCounter.cpp:
 15 (WebCore::ancestorStyleContainmentObject):
 16 (WebCore::previousInPreOrder):
 17 (WebCore::previousSiblingOrParentElement):
 18 (WebCore::makeCounterNode):
 19 (WebCore::RenderCounter::rendererSubtreeAttached):
 20 * rendering/RenderObject.cpp:
 21 (WebCore::shouldApplyStyleContainment):
 22 * rendering/RenderObject.h:
 23 * rendering/style/RenderStyle.h:
 24 (WebCore::RenderStyle::containsStyle const):
 25 * rendering/style/RenderStyleConstants.h:
 26 * style/StyleBuilderCustom.h:
 27 (WebCore::Style::BuilderCustom::applyValueContain):
 28
1292021-05-28 Martin Robinson <mrobinson@webkit.org>
230
331 More readily layout when scroll-snap properties change

Source/WebCore/css/CSSComputedStyleDeclaration.cpp

@@RefPtr<CSSValue> ComputedStyleExtractor::valueForPropertyInStyle(const RenderSty
34883488 list->append(cssValuePool.createIdentifierValue(CSSValueSize));
34893489 if (containment & Containment::Layout)
34903490 list->append(cssValuePool.createIdentifierValue(CSSValueLayout));
 3491 if (containment & Containment::Style)
 3492 list->append(cssValuePool.createIdentifierValue(CSSValueStyle));
34913493 if (containment & Containment::Paint)
34923494 list->append(cssValuePool.createIdentifierValue(CSSValuePaint));
34933495 return list;

Source/WebCore/css/parser/CSSPropertyParser.cpp

@@static RefPtr<CSSValue> consumeContain(CSSParserTokenRange& range)
38503850 if (auto singleValue = consumeIdent<CSSValueNone, CSSValueStrict, CSSValueContent>(range))
38513851 return singleValue;
38523852 auto list = CSSValueList::createSpaceSeparated();
3853  RefPtr<CSSPrimitiveValue> size, layout, paint;
 3853 RefPtr<CSSPrimitiveValue> size, layout, paint, style;
38543854 while (!range.atEnd()) {
38553855 switch (range.peek().id()) {
38563856 case CSSValueSize:

@@static RefPtr<CSSValue> consumeContain(CSSParserTokenRange& range)
38683868 return nullptr;
38693869 paint = consumeIdent(range);
38703870 break;
 3871 case CSSValueStyle:
 3872 if (style)
 3873 return nullptr;
 3874 style = consumeIdent(range);
 3875 break;
38713876 default:
38723877 return nullptr;
38733878 }

@@static RefPtr<CSSValue> consumeContain(CSSParserTokenRange& range)
38763881 list->append(size.releaseNonNull());
38773882 if (layout)
38783883 list->append(layout.releaseNonNull());
 3884 if (style)
 3885 list->append(style.releaseNonNull());
38793886 if (paint)
38803887 list->append(paint.releaseNonNull());
38813888 if (!list->length())

Source/WebCore/rendering/RenderCounter.cpp

@@static CounterMaps& counterMaps()
5757 return staticCounterMaps;
5858}
5959
 60static Element* ancestorStyleContainmentObject(const Element& element)
 61{
 62 for (Element* ancestor = element.parentElement(); ancestor; ancestor = ancestor->parentElement()) {
 63 if (ancestor->renderer() && ancestor->renderer()->style().containsStyle())
 64 return ancestor;
 65 }
 66 return nullptr;
 67}
 68
6069// This function processes the renderer tree in the order of the DOM tree
6170// including pseudo elements as defined in CSS 2.1.
6271static RenderElement* previousInPreOrder(const RenderElement& renderer)
6372{
6473 ASSERT(renderer.element());
6574 Element* previous = ElementTraversal::previousIncludingPseudo(*renderer.element());
66  while (previous && !previous->renderer())
67  previous = ElementTraversal::previousIncludingPseudo(*previous);
68  return previous ? previous->renderer() : 0;
 75 Element* styleContainAncestor = ancestorStyleContainmentObject(*renderer.element());
 76 while (true) {
 77 while (previous && !previous->renderer())
 78 previous = ElementTraversal::previousIncludingPseudo(*previous);
 79 if (!previous)
 80 return nullptr;
 81 Element* previousStyleContainAncestor = ancestorStyleContainmentObject(*previous);
 82 if (previousStyleContainAncestor == styleContainAncestor)
 83 return previous->renderer();
 84 if (!previousStyleContainAncestor)
 85 return nullptr;
 86 previous = previousStyleContainAncestor;
 87 }
6988}
7089
7190static inline Element* parentOrPseudoHostElement(const RenderElement& renderer)

@@static Element* previousSiblingOrParentElement(const Element& element)
96115 auto* parent = element.parentElement();
97116 if (parent && !parent->renderer())
98117 parent = previousSiblingOrParentElement(*parent);
 118 if (parent && parent->renderer() && parent->renderer()->style().containsStyle())
 119 return nullptr;
99120 return parent;
100121}
101122

@@static CounterNode* makeCounterNode(RenderElement& renderer, const AtomString& i
335356 maps.add(&renderer, makeUnique<CounterMap>()).iterator->value->add(identifier, newNode.copyRef());
336357 renderer.setHasCounterNodeMap(true);
337358
338  if (newNode->parent())
 359 if (newNode->parent() || shouldApplyStyleContainment(renderer))
339360 return newNode.ptr();
340361
341362 // Check if some nodes that were previously root nodes should become children of this node now.

@@static CounterNode* makeCounterNode(RenderElement& renderer, const AtomString& i
343364 auto* stayWithin = parentOrPseudoHostElement(renderer);
344365 bool skipDescendants = false;
345366 while ((currentRenderer = nextInPreOrder(*currentRenderer, stayWithin, skipDescendants))) {
346  skipDescendants = false;
 367 skipDescendants = shouldApplyStyleContainment(*currentRenderer);
347368 if (!currentRenderer->hasCounterNodeMap())
348369 continue;
349370 auto* currentCounter = maps.find(currentRenderer)->value->get(identifier);

@@void RenderCounter::rendererSubtreeAttached(RenderElement& renderer)
549570 element = renderer.generatingElement();
550571 if (element && !element->renderer())
551572 return; // No need to update if the parent is not attached yet
 573 bool crossedBoundary = false;
552574 for (RenderObject* descendant = &renderer; descendant; descendant = descendant->nextInPreOrder(&renderer)) {
553  if (is<RenderElement>(*descendant))
 575 crossedBoundary |= shouldApplyStyleContainment(*descendant);
 576 if (crossedBoundary && is<RenderElement>(*descendant))
554577 updateCounters(downcast<RenderElement>(*descendant));
555578 }
556579}

Source/WebCore/rendering/RenderObject.cpp

@@bool WebCore::shouldApplySizeContainment(const WebCore::RenderObject& renderer)
25142514{
25152515 return renderer.style().containsSize() && (!renderer.isInline() || renderer.isAtomicInlineLevelBox()) && !renderer.isRubyText() && (!renderer.isTablePart() || renderer.isTableCaption()) && !renderer.isTable();
25162516}
 2517
 2518bool WebCore::shouldApplyStyleContainment(const WebCore::RenderObject& renderer)
 2519{
 2520 return renderer.style().containsStyle() && (!renderer.isInline() || renderer.isAtomicInlineLevelBox()) && !renderer.isRubyText() && (!renderer.isTablePart() || renderer.isTableCaption()) && !renderer.isTable();
 2521}

Source/WebCore/rendering/RenderObject.h

@@void printGraphicsLayerTreeForLiveDocuments();
11971197
11981198bool shouldApplyLayoutContainment(const RenderObject&);
11991199bool shouldApplySizeContainment(const RenderObject&);
 1200bool shouldApplyStyleContainment(const RenderObject&);
12001201
12011202} // namespace WebCore
12021203

Source/WebCore/rendering/style/RenderStyle.h

@@public:
528528 OptionSet<Containment> contain() const { return m_rareNonInheritedData->contain; }
529529 bool containsLayout() const { return m_rareNonInheritedData->contain.contains(Containment::Layout); }
530530 bool containsSize() const { return m_rareNonInheritedData->contain.contains(Containment::Size); }
 531 bool containsStyle() const { return m_rareNonInheritedData->contain.contains(Containment::Style); }
531532 BoxAlignment boxAlign() const { return static_cast<BoxAlignment>(m_rareNonInheritedData->deprecatedFlexibleBox->align); }
532533 BoxDirection boxDirection() const { return static_cast<BoxDirection>(m_inheritedFlags.boxDirection); }
533534 float boxFlex() const { return m_rareNonInheritedData->deprecatedFlexibleBox->flex; }

Source/WebCore/rendering/style/RenderStyleConstants.h

@@enum class Containment : uint8_t {
12231223 Layout = 1 << 0,
12241224 Paint = 1 << 1,
12251225 Size = 1 << 2,
 1226 Style = 1 << 3,
12261227};
12271228
12281229extern const float defaultMiterLimit;

Source/WebCore/style/StyleBuilderCustom.h

@@inline void BuilderCustom::applyValueContain(BuilderState& builderState, CSSValu
12771277 case CSSValuePaint:
12781278 containment.add(Containment::Paint);
12791279 break;
 1280 case CSSValueStyle:
 1281 containment.add(Containment::Style);
 1282 break;
12801283 default:
12811284 break;
12821285 };

LayoutTests/imported/w3c/ChangeLog

 12021-05-31 Rob Buis <rbuis@igalia.com>
 2
 3 [css-contain] Support contain:style
 4 https://bugs.webkit.org/show_bug.cgi?id=226458
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 * web-platform-tests/css/css-contain/parsing/contain-computed-expected.txt:
 9 * web-platform-tests/css/css-contain/parsing/contain-valid-expected.txt:
 10
1112021-05-28 Martin Robinson <mrobinson@webkit.org>
212
313 More readily layout when scroll-snap properties change

LayoutTests/imported/w3c/web-platform-tests/css/css-contain/parsing/contain-computed-expected.txt

@@PASS Property contain value 'strict'
44PASS Property contain value 'content'
55PASS Property contain value 'size'
66PASS Property contain value 'layout'
7 FAIL Property contain value 'style' assert_true: 'style' is a supported value for contain. expected true got false
 7PASS Property contain value 'style'
88PASS Property contain value 'paint'
99PASS Property contain value 'size layout'
10 FAIL Property contain value 'style paint' assert_true: 'style paint' is a supported value for contain. expected true got false
11 FAIL Property contain value 'layout style paint' assert_true: 'layout style paint' is a supported value for contain. expected true got false
12 FAIL Property contain value 'size layout style paint' assert_true: 'size layout style paint' is a supported value for contain. expected true got false
 10PASS Property contain value 'style paint'
 11PASS Property contain value 'layout style paint'
 12PASS Property contain value 'size layout style paint'
1313PASS Property contain value 'size layout paint'
1414PASS Property contain value 'layout paint'
1515

LayoutTests/imported/w3c/web-platform-tests/css/css-contain/parsing/contain-valid-expected.txt

@@PASS e.style['contain'] = "strict" should set the property value
44PASS e.style['contain'] = "content" should set the property value
55PASS e.style['contain'] = "size" should set the property value
66PASS e.style['contain'] = "layout" should set the property value
7 FAIL e.style['contain'] = "style" should set the property value assert_not_equals: property should be set got disallowed value ""
 7PASS e.style['contain'] = "style" should set the property value
88PASS e.style['contain'] = "paint" should set the property value
99PASS e.style['contain'] = "layout size" should set the property value
10 FAIL e.style['contain'] = "paint style" should set the property value assert_not_equals: property should be set got disallowed value ""
11 FAIL e.style['contain'] = "layout style paint" should set the property value assert_not_equals: property should be set got disallowed value ""
12 FAIL e.style['contain'] = "layout paint style size" should set the property value assert_not_equals: property should be set got disallowed value ""
 10PASS e.style['contain'] = "paint style" should set the property value
 11PASS e.style['contain'] = "layout style paint" should set the property value
 12PASS e.style['contain'] = "layout paint style size" should set the property value
1313