Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(235)

Side by Side Diff: third_party/WebKit/Source/core/dom/Element.cpp

Issue 2727853002: [css-display] Support display: contents pseudo-elements.
Patch Set: Add missing nullcheck (whoops). Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Peter Kelly (pmk@post.com) 4 * (C) 2001 Peter Kelly (pmk@post.com)
5 * (C) 2001 Dirk Mueller (mueller@kde.org) 5 * (C) 2001 Dirk Mueller (mueller@kde.org)
6 * (C) 2007 David Smith (catfish.man@gmail.com) 6 * (C) 2007 David Smith (catfish.man@gmail.com)
7 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012, 2013 Apple Inc. 7 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012, 2013 Apple Inc.
8 * All rights reserved. 8 * All rights reserved.
9 * (C) 2007 Eric Seidel (eric@webkit.org) 9 * (C) 2007 Eric Seidel (eric@webkit.org)
10 * 10 *
(...skipping 1556 matching lines...) Expand 10 before | Expand all | Expand 10 after
1567 return parent->locateNamespacePrefix(namespaceToLocate); 1567 return parent->locateNamespacePrefix(namespaceToLocate);
1568 1568
1569 return nullAtom; 1569 return nullAtom;
1570 } 1570 }
1571 1571
1572 const AtomicString Element::imageSourceURL() const { 1572 const AtomicString Element::imageSourceURL() const {
1573 return getAttribute(srcAttr); 1573 return getAttribute(srcAttr);
1574 } 1574 }
1575 1575
1576 bool Element::layoutObjectIsNeeded(const ComputedStyle& style) { 1576 bool Element::layoutObjectIsNeeded(const ComputedStyle& style) {
1577 return style.display() != EDisplay::None && 1577 if (style.display() == EDisplay::None)
1578 style.display() != EDisplay::Contents; 1578 return false;
1579
1580 if (style.display() == EDisplay::Contents)
1581 return isPseudoElement();
rune 2017/03/13 10:29:50 What layout object is needed and created for the :
emilio 2017/03/13 13:28:31 Whoops, this is leftover from the previous approac
1582
1583 return true;
1579 } 1584 }
1580 1585
1581 LayoutObject* Element::createLayoutObject(const ComputedStyle& style) { 1586 LayoutObject* Element::createLayoutObject(const ComputedStyle& style) {
1582 return LayoutObject::createObject(this, style); 1587 return LayoutObject::createObject(this, style);
1583 } 1588 }
1584 1589
1585 Node::InsertionNotificationRequest Element::insertedInto( 1590 Node::InsertionNotificationRequest Element::insertedInto(
1586 ContainerNode* insertionPoint) { 1591 ContainerNode* insertionPoint) {
1587 // need to do superclass processing first so isConnected() is true 1592 // need to do superclass processing first so isConnected() is true
1588 // by the time we reach updateId 1593 // by the time we reach updateId
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after
1997 if (localChange != NoChange) { 2002 if (localChange != NoChange) {
1998 layoutObject->setStyle(newStyle.get()); 2003 layoutObject->setStyle(newStyle.get());
1999 } else { 2004 } else {
2000 // Although no change occurred, we use the new style so that the cousin 2005 // Although no change occurred, we use the new style so that the cousin
2001 // style sharing code won't get fooled into believing this style is the 2006 // style sharing code won't get fooled into believing this style is the
2002 // same. 2007 // same.
2003 // FIXME: We may be able to remove this hack, see discussion in 2008 // FIXME: We may be able to remove this hack, see discussion in
2004 // https://codereview.chromium.org/30453002/ 2009 // https://codereview.chromium.org/30453002/
2005 layoutObject->setStyleInternal(newStyle.get()); 2010 layoutObject->setStyleInternal(newStyle.get());
2006 } 2011 }
2007 } else if (localChange != NoChange && 2012 } else {
2008 shouldStoreNonLayoutObjectComputedStyle(*newStyle)) { 2013 if (localChange != NoChange) {
2009 storeNonLayoutObjectComputedStyle(newStyle); 2014 if (shouldStoreNonLayoutObjectComputedStyle(*newStyle))
2015 storeNonLayoutObjectComputedStyle(newStyle);
2016 else if (hasRareData())
2017 elementRareData()->clearComputedStyle();
2018 }
2010 } 2019 }
2011 2020
2012 if (getStyleChangeType() >= SubtreeStyleChange) 2021 if (getStyleChangeType() >= SubtreeStyleChange)
2013 return Force; 2022 return Force;
2014 2023
2015 if (change > Inherit || localChange > Inherit) 2024 if (change > Inherit || localChange > Inherit)
2016 return max(localChange, change); 2025 return max(localChange, change);
2017 2026
2018 if (localChange < IndependentInherit) { 2027 if (localChange < IndependentInherit) {
2019 if (oldStyle->hasChildDependentFlags()) { 2028 if (oldStyle->hasChildDependentFlags()) {
(...skipping 1154 matching lines...) Expand 10 before | Expand all | Expand 10 after
3174 ElementRareData& rareData = ensureElementRareData(); 3183 ElementRareData& rareData = ensureElementRareData();
3175 if (!rareData.computedStyle()) 3184 if (!rareData.computedStyle())
3176 rareData.setComputedStyle( 3185 rareData.setComputedStyle(
3177 document().styleForElementIgnoringPendingStylesheets(this)); 3186 document().styleForElementIgnoringPendingStylesheets(this));
3178 elementStyle = rareData.computedStyle(); 3187 elementStyle = rareData.computedStyle();
3179 } 3188 }
3180 3189
3181 if (!pseudoElementSpecifier) 3190 if (!pseudoElementSpecifier)
3182 return elementStyle; 3191 return elementStyle;
3183 3192
3184 if (ComputedStyle* pseudoElementStyle = 3193 if (ComputedStyle* cached =
3185 elementStyle->getCachedPseudoStyle(pseudoElementSpecifier)) 3194 elementStyle->getCachedPseudoStyle(pseudoElementSpecifier))
3186 return pseudoElementStyle; 3195 return cached;
rune 2017/03/13 10:29:50 This and the code below duplicates the code in Ele
emilio 2017/03/13 13:28:31 No, I can't. We use pseudoStyleForElement instead
3187 3196
3188 // TODO(ecobos): Passing two times elementStyle may be wrong, though we don't 3197 const ComputedStyle* layoutParentStyle = elementStyle;
3189 // support display: contents elements' pseudo-elements yet, so this is not a 3198 if (hasDisplayContentsStyle()) {
3190 // problem for now. 3199 LayoutObject* parentLayoutObject =
3200 LayoutTreeBuilderTraversal::parentLayoutObject(*this);
3201 if (parentLayoutObject)
3202 layoutParentStyle = parentLayoutObject->style();
3203 }
3204
3191 RefPtr<ComputedStyle> result = 3205 RefPtr<ComputedStyle> result =
3192 document().ensureStyleResolver().pseudoStyleForElement( 3206 document().ensureStyleResolver().pseudoStyleForElement(
3193 this, PseudoStyleRequest(pseudoElementSpecifier, 3207 this,
3194 PseudoStyleRequest::ForComputedStyle), 3208 PseudoStyleRequest(pseudoElementSpecifier,
3195 elementStyle, elementStyle); 3209 PseudoStyleRequest::ForComputedStyle),
3210 elementStyle, layoutParentStyle);
3196 DCHECK(result); 3211 DCHECK(result);
3197 return elementStyle->addCachedPseudoStyle(result.release()); 3212 return elementStyle->addCachedPseudoStyle(result.release());
3198 } 3213 }
3199 3214
3200 const ComputedStyle* Element::nonLayoutObjectComputedStyle() const { 3215 const ComputedStyle* Element::nonLayoutObjectComputedStyle() const {
3201 if (layoutObject() || !hasRareData()) 3216 if (layoutObject() || !hasRareData())
3202 return nullptr; 3217 return nullptr;
3203 3218
3204 return elementRareData()->computedStyle(); 3219 return elementRareData()->computedStyle();
3205 } 3220 }
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
3269 PseudoElement* element = pseudoElement(pseudoId); 3284 PseudoElement* element = pseudoElement(pseudoId);
3270 3285
3271 if (element && (change == UpdatePseudoElements || 3286 if (element && (change == UpdatePseudoElements ||
3272 element->shouldCallRecalcStyle(change))) { 3287 element->shouldCallRecalcStyle(change))) {
3273 if (pseudoId == PseudoIdFirstLetter && updateFirstLetter(element)) 3288 if (pseudoId == PseudoIdFirstLetter && updateFirstLetter(element))
3274 return; 3289 return;
3275 3290
3276 // Need to clear the cached style if the PseudoElement wants a recalc so it 3291 // Need to clear the cached style if the PseudoElement wants a recalc so it
3277 // computes a new style. 3292 // computes a new style.
3278 if (element->needsStyleRecalc()) 3293 if (element->needsStyleRecalc())
3279 layoutObject()->mutableStyle()->removeCachedPseudoStyle(pseudoId); 3294 mutableComputedStyle()->removeCachedPseudoStyle(pseudoId);
3280 3295
3281 // PseudoElement styles hang off their parent element's style so if we 3296 // PseudoElement styles hang off their parent element's style so if we
3282 // needed a style recalc we should Force one on the pseudo. FIXME: We 3297 // needed a style recalc we should Force one on the pseudo. FIXME: We
3283 // should figure out the right text sibling to pass. 3298 // should figure out the right text sibling to pass.
3284 element->recalcStyle(change == UpdatePseudoElements ? Force : change); 3299 element->recalcStyle(change == UpdatePseudoElements ? Force : change);
3285 3300
3286 // Wait until our parent is not displayed or 3301 // Wait until our parent is not displayed or
3287 // pseudoElementLayoutObjectIsNeeded is false, otherwise we could 3302 // pseudoElementLayoutObjectIsNeeded is false, otherwise we could
3288 // continuously create and destroy PseudoElements when 3303 // continuously create and destroy PseudoElements when
3289 // LayoutObject::isChildAllowed on our parent returns false for the 3304 // LayoutObject::isChildAllowed on our parent returns false for the
3290 // PseudoElement's layoutObject for each style recalc. 3305 // PseudoElement's layoutObject for each style recalc.
3291 if (!layoutObject() || 3306 if (!canHaveGeneratedPseudo(pseudoId) ||
3292 !pseudoElementLayoutObjectIsNeeded( 3307 !pseudoElementLayoutObjectIsNeeded(pseudoStyle(pseudoId)))
3293 layoutObject()->getCachedPseudoStyle(pseudoId)))
3294 elementRareData()->setPseudoElement(pseudoId, nullptr); 3308 elementRareData()->setPseudoElement(pseudoId, nullptr);
3295 } else if (pseudoId == PseudoIdFirstLetter && element && 3309 } else if (pseudoId == PseudoIdFirstLetter && element &&
3296 change >= UpdatePseudoElements && 3310 change >= UpdatePseudoElements &&
3297 !FirstLetterPseudoElement::firstLetterTextLayoutObject(*element)) { 3311 !FirstLetterPseudoElement::firstLetterTextLayoutObject(*element)) {
3298 // This can happen if we change to a float, for example. We need to cleanup 3312 // This can happen if we change to a float, for example. We need to cleanup
3299 // the first-letter pseudoElement and then fix the text of the original 3313 // the first-letter pseudoElement and then fix the text of the original
3300 // remaining text layoutObject. This can be seen in Test 7 of 3314 // remaining text layoutObject. This can be seen in Test 7 of
3301 // fast/css/first-letter-removed-added.html 3315 // fast/css/first-letter-removed-added.html
3302 elementRareData()->setPseudoElement(pseudoId, nullptr); 3316 elementRareData()->setPseudoElement(pseudoId, nullptr);
3303 } else if (change >= UpdatePseudoElements) { 3317 } else if (change >= UpdatePseudoElements) {
(...skipping 16 matching lines...) Expand all
3320 // incorrect results due to setting the first letter back. 3334 // incorrect results due to setting the first letter back.
3321 if (remainingTextLayoutObject) 3335 if (remainingTextLayoutObject)
3322 element->reattachLayoutTree(); 3336 element->reattachLayoutTree();
3323 else 3337 else
3324 elementRareData()->setPseudoElement(PseudoIdFirstLetter, nullptr); 3338 elementRareData()->setPseudoElement(PseudoIdFirstLetter, nullptr);
3325 return true; 3339 return true;
3326 } 3340 }
3327 return false; 3341 return false;
3328 } 3342 }
3329 3343
3344 ComputedStyle* Element::pseudoStyle(PseudoId pseudoId) const {
3345 ComputedStyle* style = mutableComputedStyle();
3346 DCHECK(pseudoId < FirstInternalPseudoId);
3347 if (!style->hasPseudoStyle(pseudoId))
3348 return nullptr;
3349
3350 if (ComputedStyle* cached = style->getCachedPseudoStyle(pseudoId))
3351 return cached;
3352 RefPtr<ComputedStyle> uncached = getUncachedPseudoStyle(pseudoId);
3353 if (uncached)
3354 return style->addCachedPseudoStyle(uncached.release());
3355 return nullptr;
3356 }
3357
3358 PassRefPtr<ComputedStyle> Element::getUncachedPseudoStyle(
3359 PseudoId pseudoId) const {
3360 if (pseudoId == PseudoIdBefore || pseudoId == PseudoIdAfter) {
3361 LayoutObject* parentLayoutObject = layoutObject();
3362 if (!parentLayoutObject && hasDisplayContentsStyle()) {
3363 parentLayoutObject =
3364 LayoutTreeBuilderTraversal::parentLayoutObject(*this);
3365 }
3366 if (!parentLayoutObject)
3367 return nullptr;
3368 return document().ensureStyleResolver().pseudoStyleForElement(
3369 const_cast<Element*>(this), PseudoStyleRequest(pseudoId),
3370 computedStyle(), parentLayoutObject->style());
3371 }
3372 if (!layoutObject())
3373 return nullptr;
3374 return layoutObject()->getUncachedPseudoStyle(PseudoStyleRequest(pseudoId));
3375 }
3376
3377 // For display: contents elements, we still need to generate ::before and
3378 // ::after, but the rest of the pseudo-elements should only be used for elements
3379 // with an actual layout object.
3380 bool Element::canHaveGeneratedPseudo(PseudoId pseudoId) const {
3381 if (hasDisplayContentsStyle())
3382 return pseudoId == PseudoIdBefore || pseudoId == PseudoIdAfter;
3383 return !!layoutObject();
3384 }
3385
3330 void Element::createPseudoElementIfNeeded(PseudoId pseudoId) { 3386 void Element::createPseudoElementIfNeeded(PseudoId pseudoId) {
3331 if (isPseudoElement()) 3387 if (isPseudoElement())
3332 return; 3388 return;
3333 3389
3334 // Document::ensureStyleResolver is not inlined and shows up on profiles, 3390 // Document::ensureStyleResolver is not inlined and shows up on profiles,
3335 // avoid it here. 3391 // avoid it here.
3336 PseudoElement* element = 3392 PseudoElement* element =
3337 document().styleEngine().ensureResolver().createPseudoElementIfNeeded( 3393 document().styleEngine().ensureResolver().createPseudoElementIfNeeded(
3338 *this, pseudoId); 3394 *this, pseudoId);
3339 if (!element) 3395 if (!element)
(...skipping 845 matching lines...) Expand 10 before | Expand all | Expand 10 after
4185 } 4241 }
4186 4242
4187 DEFINE_TRACE_WRAPPERS(Element) { 4243 DEFINE_TRACE_WRAPPERS(Element) {
4188 if (hasRareData()) { 4244 if (hasRareData()) {
4189 visitor->traceWrappers(elementRareData()); 4245 visitor->traceWrappers(elementRareData());
4190 } 4246 }
4191 ContainerNode::traceWrappers(visitor); 4247 ContainerNode::traceWrappers(visitor);
4192 } 4248 }
4193 4249
4194 } // namespace blink 4250 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698