OLD | NEW |
---|---|
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 Loading... | |
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/06 10:13:33
Why? Pseudo elements on which display applies can
emilio
2017/03/06 16:52:09
Well, that's definitely not what Gecko does fwiw.
rune
2017/03/07 13:46:01
This case below fails in Gecko. I think that's a b
| |
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 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1802 | 1807 |
1803 if (context.clearInvalidation) | 1808 if (context.clearInvalidation) |
1804 document().styleEngine().styleInvalidator().clearInvalidation(*this); | 1809 document().styleEngine().styleInvalidator().clearInvalidation(*this); |
1805 | 1810 |
1806 setNeedsResizeObserverUpdate(); | 1811 setNeedsResizeObserverUpdate(); |
1807 | 1812 |
1808 DCHECK(needsAttach()); | 1813 DCHECK(needsAttach()); |
1809 } | 1814 } |
1810 | 1815 |
1811 bool Element::pseudoStyleCacheIsInvalid(const ComputedStyle* currentStyle, | 1816 bool Element::pseudoStyleCacheIsInvalid(const ComputedStyle* currentStyle, |
1812 ComputedStyle* newStyle) { | 1817 ComputedStyle* newStyle) { |
rune
2017/03/06 10:13:33
This method has a terrible name and an incomprehen
emilio
2017/03/06 16:52:09
lol, fun.
| |
1813 DCHECK_EQ(currentStyle, computedStyle()); | 1818 DCHECK_EQ(currentStyle, computedStyle()); |
1814 DCHECK(layoutObject()); | |
1815 | 1819 |
1816 if (!currentStyle) | 1820 if (!currentStyle) |
1817 return false; | 1821 return false; |
1818 | 1822 |
1819 const PseudoStyleCache* pseudoStyleCache = currentStyle->cachedPseudoStyles(); | 1823 const PseudoStyleCache* pseudoStyleCache = currentStyle->cachedPseudoStyles(); |
1820 if (!pseudoStyleCache) | 1824 if (!pseudoStyleCache) |
1821 return false; | 1825 return false; |
1822 | 1826 |
1827 if (!layoutObject() && currentStyle->display() != EDisplay::Contents) | |
1828 return true; | |
1829 | |
1830 const ComputedStyle* layoutParentStyle = newStyle; | |
1831 if (!layoutObject()) { | |
1832 LayoutObject* parentLayoutObject = | |
1833 LayoutTreeBuilderTraversal::parentLayoutObject(*this); | |
1834 DCHECK(parentLayoutObject); | |
1835 layoutParentStyle = parentLayoutObject->style(); | |
1836 } | |
1837 | |
1823 size_t cacheSize = pseudoStyleCache->size(); | 1838 size_t cacheSize = pseudoStyleCache->size(); |
1824 for (size_t i = 0; i < cacheSize; ++i) { | 1839 for (size_t i = 0; i < cacheSize; ++i) { |
1825 RefPtr<ComputedStyle> newPseudoStyle; | 1840 RefPtr<ComputedStyle> newPseudoStyle; |
1826 RefPtr<ComputedStyle> oldPseudoStyle = pseudoStyleCache->at(i); | 1841 RefPtr<ComputedStyle> oldPseudoStyle = pseudoStyleCache->at(i); |
1827 PseudoId pseudoId = oldPseudoStyle->styleType(); | 1842 PseudoId pseudoId = oldPseudoStyle->styleType(); |
1828 if (pseudoId == PseudoIdFirstLine || pseudoId == PseudoIdFirstLineInherited) | 1843 if (!isPseudoElementAllowed(pseudoId)) |
1844 return true; | |
rune
2017/03/06 10:13:33
This method is buggy in the first place in that it
| |
1845 if (pseudoId == PseudoIdBefore || pseudoId == PseudoIdAfter) { | |
1846 newPseudoStyle = document().ensureStyleResolver().pseudoStyleForElement( | |
1847 this, PseudoStyleRequest(pseudoId), newStyle, layoutParentStyle); | |
1848 } else if (pseudoId == PseudoIdFirstLine || | |
1849 pseudoId == PseudoIdFirstLineInherited) { | |
1829 newPseudoStyle = layoutObject()->uncachedFirstLineStyle(newStyle); | 1850 newPseudoStyle = layoutObject()->uncachedFirstLineStyle(newStyle); |
1830 else | 1851 } else { |
1831 newPseudoStyle = layoutObject()->getUncachedPseudoStyle( | 1852 newPseudoStyle = layoutObject()->getUncachedPseudoStyle( |
1832 PseudoStyleRequest(pseudoId), newStyle, newStyle); | 1853 PseudoStyleRequest(pseudoId), newStyle, newStyle); |
1854 } | |
1833 if (!newPseudoStyle) | 1855 if (!newPseudoStyle) |
1834 return true; | 1856 return true; |
1835 if (*oldPseudoStyle != *newPseudoStyle || | 1857 if (*oldPseudoStyle != *newPseudoStyle || |
1836 oldPseudoStyle->font().loadingCustomFonts() != | 1858 oldPseudoStyle->font().loadingCustomFonts() != |
1837 newPseudoStyle->font().loadingCustomFonts()) { | 1859 newPseudoStyle->font().loadingCustomFonts()) { |
1838 if (pseudoId < FirstInternalPseudoId) | 1860 if (pseudoId < FirstInternalPseudoId) |
1839 newStyle->setHasPseudoStyle(pseudoId); | 1861 newStyle->setHasPseudoStyle(pseudoId); |
1840 newStyle->addCachedPseudoStyle(newPseudoStyle); | 1862 newStyle->addCachedPseudoStyle(newPseudoStyle); |
1841 if (pseudoId == PseudoIdFirstLine || | 1863 if (pseudoId == PseudoIdFirstLine || |
1842 pseudoId == PseudoIdFirstLineInherited) | 1864 pseudoId == PseudoIdFirstLineInherited) { |
1843 layoutObject()->firstLineStyleDidChange(*oldPseudoStyle, | 1865 layoutObject()->firstLineStyleDidChange(*oldPseudoStyle, |
1844 *newPseudoStyle); | 1866 *newPseudoStyle); |
1867 } | |
1845 return true; | 1868 return true; |
1846 } | 1869 } |
1847 } | 1870 } |
1848 return false; | 1871 return false; |
1849 } | 1872 } |
1850 | 1873 |
1851 PassRefPtr<ComputedStyle> Element::styleForLayoutObject() { | 1874 PassRefPtr<ComputedStyle> Element::styleForLayoutObject() { |
1852 DCHECK(document().inStyleRecalc()); | 1875 DCHECK(document().inStyleRecalc()); |
1853 | 1876 |
1854 RefPtr<ComputedStyle> style; | 1877 RefPtr<ComputedStyle> style; |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2036 pseudoStyleCacheIsInvalid(oldStyle.get(), newStyle.get())) { | 2059 pseudoStyleCacheIsInvalid(oldStyle.get(), newStyle.get())) { |
2037 layoutObject->setStyle(newStyle.get()); | 2060 layoutObject->setStyle(newStyle.get()); |
2038 } else { | 2061 } else { |
2039 // Although no change occurred, we use the new style so that the cousin | 2062 // Although no change occurred, we use the new style so that the cousin |
2040 // style sharing code won't get fooled into believing this style is the | 2063 // style sharing code won't get fooled into believing this style is the |
2041 // same. | 2064 // same. |
2042 // FIXME: We may be able to remove this hack, see discussion in | 2065 // FIXME: We may be able to remove this hack, see discussion in |
2043 // https://codereview.chromium.org/30453002/ | 2066 // https://codereview.chromium.org/30453002/ |
2044 layoutObject->setStyleInternal(newStyle.get()); | 2067 layoutObject->setStyleInternal(newStyle.get()); |
2045 } | 2068 } |
2046 } else if (localChange != NoChange && | 2069 } else { |
2047 shouldStoreNonLayoutObjectComputedStyle(*newStyle)) { | 2070 if (localChange != NoChange || |
2048 storeNonLayoutObjectComputedStyle(newStyle); | 2071 pseudoStyleCacheIsInvalid(oldStyle.get(), newStyle.get())) { |
2072 if (shouldStoreNonLayoutObjectComputedStyle(*newStyle)) | |
2073 storeNonLayoutObjectComputedStyle(newStyle); | |
2074 else if (hasRareData()) | |
2075 elementRareData()->clearComputedStyle(); | |
rune
2017/03/06 10:13:33
Is the clearComputedStyle() here a fix made necess
emilio
2017/03/06 17:03:46
I made it thinking on pseudos. It doesn't fix any
rune
2017/03/07 13:46:01
Acknowledged.
| |
2076 } | |
2049 } | 2077 } |
2050 | 2078 |
2051 if (getStyleChangeType() >= SubtreeStyleChange) | 2079 if (getStyleChangeType() >= SubtreeStyleChange) |
2052 return Force; | 2080 return Force; |
2053 | 2081 |
2054 if (change > Inherit || localChange > Inherit) | 2082 if (change > Inherit || localChange > Inherit) |
2055 return max(localChange, change); | 2083 return max(localChange, change); |
2056 | 2084 |
2057 if (localChange < IndependentInherit) { | 2085 if (localChange < IndependentInherit) { |
2058 if (oldStyle->hasChildDependentFlags()) { | 2086 if (oldStyle->hasChildDependentFlags()) { |
(...skipping 1131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3190 ElementRareData& rareData = ensureElementRareData(); | 3218 ElementRareData& rareData = ensureElementRareData(); |
3191 if (!rareData.computedStyle()) | 3219 if (!rareData.computedStyle()) |
3192 rareData.setComputedStyle( | 3220 rareData.setComputedStyle( |
3193 document().styleForElementIgnoringPendingStylesheets(this)); | 3221 document().styleForElementIgnoringPendingStylesheets(this)); |
3194 elementStyle = rareData.computedStyle(); | 3222 elementStyle = rareData.computedStyle(); |
3195 } | 3223 } |
3196 | 3224 |
3197 if (!pseudoElementSpecifier) | 3225 if (!pseudoElementSpecifier) |
3198 return elementStyle; | 3226 return elementStyle; |
3199 | 3227 |
3200 if (ComputedStyle* pseudoElementStyle = | 3228 if (ComputedStyle* cached = |
3201 elementStyle->getCachedPseudoStyle(pseudoElementSpecifier)) | 3229 elementStyle->getCachedPseudoStyle(pseudoElementSpecifier)) |
3202 return pseudoElementStyle; | 3230 return cached; |
3203 | 3231 |
3204 // TODO(ecobos): Passing two times elementStyle may be wrong, though we don't | 3232 const ComputedStyle* layoutParentStyle = elementStyle; |
3205 // support display: contents elements' pseudo-elements yet, so this is not a | 3233 if (hasDisplayContentsStyle()) { |
3206 // problem for now. | 3234 LayoutObject* parentLayoutObject = |
3235 LayoutTreeBuilderTraversal::parentLayoutObject(*this); | |
3236 if (parentLayoutObject) | |
3237 layoutParentStyle = parentLayoutObject->style(); | |
3238 } | |
3239 | |
3207 RefPtr<ComputedStyle> result = | 3240 RefPtr<ComputedStyle> result = |
3208 document().ensureStyleResolver().pseudoStyleForElement( | 3241 document().ensureStyleResolver().pseudoStyleForElement( |
3209 this, PseudoStyleRequest(pseudoElementSpecifier, | 3242 this, |
3210 PseudoStyleRequest::ForComputedStyle), | 3243 PseudoStyleRequest(pseudoElementSpecifier, |
3211 elementStyle, elementStyle); | 3244 PseudoStyleRequest::ForComputedStyle), |
3245 elementStyle, layoutParentStyle); | |
3212 DCHECK(result); | 3246 DCHECK(result); |
3213 return elementStyle->addCachedPseudoStyle(result.release()); | 3247 return elementStyle->addCachedPseudoStyle(result.release()); |
3214 } | 3248 } |
3215 | 3249 |
3216 const ComputedStyle* Element::nonLayoutObjectComputedStyle() const { | 3250 const ComputedStyle* Element::nonLayoutObjectComputedStyle() const { |
3217 if (layoutObject() || !hasRareData()) | 3251 if (layoutObject() || !hasRareData()) |
3218 return nullptr; | 3252 return nullptr; |
3219 | 3253 |
3220 return elementRareData()->computedStyle(); | 3254 return elementRareData()->computedStyle(); |
3221 } | 3255 } |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3285 PseudoElement* element = pseudoElement(pseudoId); | 3319 PseudoElement* element = pseudoElement(pseudoId); |
3286 | 3320 |
3287 if (element && (change == UpdatePseudoElements || | 3321 if (element && (change == UpdatePseudoElements || |
3288 element->shouldCallRecalcStyle(change))) { | 3322 element->shouldCallRecalcStyle(change))) { |
3289 if (pseudoId == PseudoIdFirstLetter && updateFirstLetter(element)) | 3323 if (pseudoId == PseudoIdFirstLetter && updateFirstLetter(element)) |
3290 return; | 3324 return; |
3291 | 3325 |
3292 // Need to clear the cached style if the PseudoElement wants a recalc so it | 3326 // Need to clear the cached style if the PseudoElement wants a recalc so it |
3293 // computes a new style. | 3327 // computes a new style. |
3294 if (element->needsStyleRecalc()) | 3328 if (element->needsStyleRecalc()) |
3295 layoutObject()->mutableStyle()->removeCachedPseudoStyle(pseudoId); | 3329 mutableComputedStyle()->removeCachedPseudoStyle(pseudoId); |
3296 | 3330 |
3297 // PseudoElement styles hang off their parent element's style so if we | 3331 // PseudoElement styles hang off their parent element's style so if we |
3298 // needed a style recalc we should Force one on the pseudo. FIXME: We | 3332 // needed a style recalc we should Force one on the pseudo. FIXME: We |
3299 // should figure out the right text sibling to pass. | 3333 // should figure out the right text sibling to pass. |
3300 element->recalcStyle(change == UpdatePseudoElements ? Force : change); | 3334 element->recalcStyle(change == UpdatePseudoElements ? Force : change); |
3301 | 3335 |
3302 // Wait until our parent is not displayed or | 3336 // Wait until our parent is not displayed or |
3303 // pseudoElementLayoutObjectIsNeeded is false, otherwise we could | 3337 // pseudoElementLayoutObjectIsNeeded is false, otherwise we could |
3304 // continuously create and destroy PseudoElements when | 3338 // continuously create and destroy PseudoElements when |
3305 // LayoutObject::isChildAllowed on our parent returns false for the | 3339 // LayoutObject::isChildAllowed on our parent returns false for the |
3306 // PseudoElement's layoutObject for each style recalc. | 3340 // PseudoElement's layoutObject for each style recalc. |
3307 if (!layoutObject() || | 3341 if (!isPseudoElementAllowed(pseudoId) || |
3308 !pseudoElementLayoutObjectIsNeeded( | 3342 !pseudoElementLayoutObjectIsNeeded( |
3309 layoutObject()->getCachedPseudoStyle(pseudoId))) | 3343 getCachedPseudoStyleOrCache(pseudoId))) |
3310 elementRareData()->setPseudoElement(pseudoId, nullptr); | 3344 elementRareData()->setPseudoElement(pseudoId, nullptr); |
3311 } else if (pseudoId == PseudoIdFirstLetter && element && | 3345 } else if (pseudoId == PseudoIdFirstLetter && element && |
3312 change >= UpdatePseudoElements && | 3346 change >= UpdatePseudoElements && |
3313 !FirstLetterPseudoElement::firstLetterTextLayoutObject(*element)) { | 3347 !FirstLetterPseudoElement::firstLetterTextLayoutObject(*element)) { |
3314 // This can happen if we change to a float, for example. We need to cleanup | 3348 // This can happen if we change to a float, for example. We need to cleanup |
3315 // the first-letter pseudoElement and then fix the text of the original | 3349 // the first-letter pseudoElement and then fix the text of the original |
3316 // remaining text layoutObject. This can be seen in Test 7 of | 3350 // remaining text layoutObject. This can be seen in Test 7 of |
3317 // fast/css/first-letter-removed-added.html | 3351 // fast/css/first-letter-removed-added.html |
3318 elementRareData()->setPseudoElement(pseudoId, nullptr); | 3352 elementRareData()->setPseudoElement(pseudoId, nullptr); |
3319 } else if (change >= UpdatePseudoElements) { | 3353 } else if (change >= UpdatePseudoElements) { |
(...skipping 16 matching lines...) Expand all Loading... | |
3336 // incorrect results due to setting the first letter back. | 3370 // incorrect results due to setting the first letter back. |
3337 if (remainingTextLayoutObject) | 3371 if (remainingTextLayoutObject) |
3338 element->reattachLayoutTree(); | 3372 element->reattachLayoutTree(); |
3339 else | 3373 else |
3340 elementRareData()->setPseudoElement(PseudoIdFirstLetter, nullptr); | 3374 elementRareData()->setPseudoElement(PseudoIdFirstLetter, nullptr); |
3341 return true; | 3375 return true; |
3342 } | 3376 } |
3343 return false; | 3377 return false; |
3344 } | 3378 } |
3345 | 3379 |
3380 ComputedStyle* Element::getCachedPseudoStyleOrCache(PseudoId pseudoId) const { | |
rune
2017/03/06 10:13:33
I don't understand the name of this method.
emilio
2017/03/06 16:52:09
It explicitly states what getCachedPseudoStyle did
rune
2017/03/07 13:46:01
I read that name as "return the cached pseudo styl
| |
3381 ComputedStyle* style = mutableComputedStyle(); | |
3382 if (pseudoId < FirstInternalPseudoId && !style->hasPseudoStyle(pseudoId)) | |
3383 return nullptr; | |
rune
2017/03/07 13:46:01
I don't think we use cache entries for internal ps
| |
3384 | |
3385 if (ComputedStyle* cached = style->getCachedPseudoStyle(pseudoId)) | |
3386 return cached; | |
3387 RefPtr<ComputedStyle> uncached = getUncachedPseudoStyle(pseudoId); | |
3388 if (uncached) | |
3389 return style->addCachedPseudoStyle(uncached.release()); | |
3390 return nullptr; | |
3391 } | |
3392 | |
3393 PassRefPtr<ComputedStyle> Element::getUncachedPseudoStyle( | |
3394 PseudoId pseudoId) const { | |
3395 if (pseudoId == PseudoIdBefore || pseudoId == PseudoIdAfter) { | |
3396 LayoutObject* parentLayoutObject = layoutObject(); | |
3397 if (!parentLayoutObject && hasDisplayContentsStyle()) { | |
3398 parentLayoutObject = | |
3399 LayoutTreeBuilderTraversal::parentLayoutObject(*this); | |
3400 } | |
3401 if (!parentLayoutObject) | |
3402 return nullptr; | |
3403 return document().ensureStyleResolver().pseudoStyleForElement( | |
3404 const_cast<Element*>(this), PseudoStyleRequest(pseudoId), | |
3405 computedStyle(), parentLayoutObject->style()); | |
3406 } | |
3407 if (!layoutObject()) | |
3408 return nullptr; | |
3409 return layoutObject()->getUncachedPseudoStyle(PseudoStyleRequest(pseudoId)); | |
3410 } | |
3411 | |
3412 // For display: contents elements, we still need to generate ::before and | |
3413 // ::after, but the rest of the pseudo-elements should only be used for elements | |
3414 // with an actual layout object. | |
rune
2017/03/06 10:13:33
I was just thinking about this in relation to ::se
emilio
2017/03/06 16:52:09
Note that this works with this patch, because I in
rune
2017/03/07 13:46:01
I find it hard to understand what "allowed" means
| |
3415 bool Element::isPseudoElementAllowed(PseudoId pseudoId) const { | |
3416 if (hasDisplayContentsStyle()) | |
3417 return pseudoId == PseudoIdBefore || pseudoId == PseudoIdAfter; | |
3418 return !!layoutObject(); | |
3419 } | |
3420 | |
3346 void Element::createPseudoElementIfNeeded(PseudoId pseudoId) { | 3421 void Element::createPseudoElementIfNeeded(PseudoId pseudoId) { |
3347 if (isPseudoElement()) | 3422 if (isPseudoElement()) |
3348 return; | 3423 return; |
3349 | 3424 |
3350 // Document::ensureStyleResolver is not inlined and shows up on profiles, | 3425 // Document::ensureStyleResolver is not inlined and shows up on profiles, |
3351 // avoid it here. | 3426 // avoid it here. |
3352 PseudoElement* element = | 3427 PseudoElement* element = |
3353 document().styleEngine().ensureResolver().createPseudoElementIfNeeded( | 3428 document().styleEngine().ensureResolver().createPseudoElementIfNeeded( |
3354 *this, pseudoId); | 3429 *this, pseudoId); |
3355 if (!element) | 3430 if (!element) |
(...skipping 845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4201 } | 4276 } |
4202 | 4277 |
4203 DEFINE_TRACE_WRAPPERS(Element) { | 4278 DEFINE_TRACE_WRAPPERS(Element) { |
4204 if (hasRareData()) { | 4279 if (hasRareData()) { |
4205 visitor->traceWrappers(elementRareData()); | 4280 visitor->traceWrappers(elementRareData()); |
4206 } | 4281 } |
4207 ContainerNode::traceWrappers(visitor); | 4282 ContainerNode::traceWrappers(visitor); |
4208 } | 4283 } |
4209 | 4284 |
4210 } // namespace blink | 4285 } // namespace blink |
OLD | NEW |