LEFT | RIGHT |
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-2017 Apple Inc. All rights reserved. | 7 * Copyright (C) 2004-2017 Apple Inc. All rights reserved. |
8 * (C) 2007 Eric Seidel (eric@webkit.org) | 8 * (C) 2007 Eric Seidel (eric@webkit.org) |
9 * | 9 * |
10 * This library is free software; you can redistribute it and/or | 10 * This library is free software; you can redistribute it and/or |
(...skipping 678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
689 bool insideFixed; | 689 bool insideFixed; |
690 LayoutRect absoluteBounds = renderer()->absoluteAnchorRect(&insideFixed); | 690 LayoutRect absoluteBounds = renderer()->absoluteAnchorRect(&insideFixed); |
691 if (centerIfNotVisible) | 691 if (centerIfNotVisible) |
692 renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, absoluteBou
nds, insideFixed, ScrollAlignment::alignCenterIfNotVisible, ScrollAlignment::ali
gnCenterIfNotVisible, ShouldAllowCrossOriginScrolling::No); | 692 renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, absoluteBou
nds, insideFixed, ScrollAlignment::alignCenterIfNotVisible, ScrollAlignment::ali
gnCenterIfNotVisible, ShouldAllowCrossOriginScrolling::No); |
693 else | 693 else |
694 renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, absoluteBou
nds, insideFixed, ScrollAlignment::alignToEdgeIfNotVisible, ScrollAlignment::ali
gnToEdgeIfNotVisible, ShouldAllowCrossOriginScrolling::No); | 694 renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, absoluteBou
nds, insideFixed, ScrollAlignment::alignToEdgeIfNotVisible, ScrollAlignment::ali
gnToEdgeIfNotVisible, ShouldAllowCrossOriginScrolling::No); |
695 } | 695 } |
696 | 696 |
697 void Element::scrollBy(const ScrollToOptions& options) | 697 void Element::scrollBy(const ScrollToOptions& options) |
698 { | 698 { |
699 return scrollBy(options.left.value_or(0), options.top.value_or(0)); | 699 ScrollToOptions scrollToOptions = normalizeNonFiniteCoordinatesOrFallBackTo(
options, 0, 0); |
700 } | 700 scrollToOptions.left.value() += scrollLeft(); |
701 | 701 scrollToOptions.top.value() += scrollTop(); |
702 static inline double normalizeNonFiniteValue(double f) | 702 scrollTo(scrollToOptions); |
703 { | |
704 return std::isfinite(f) ? f : 0; | |
705 } | 703 } |
706 | 704 |
707 void Element::scrollBy(double x, double y) | 705 void Element::scrollBy(double x, double y) |
708 { | 706 { |
709 scrollTo(scrollLeft() + normalizeNonFiniteValue(x), scrollTop() + normalizeN
onFiniteValue(y)); | 707 scrollBy({ x, y }); |
710 } | 708 } |
711 | 709 |
712 void Element::scrollTo(const ScrollToOptions& options, ScrollClamping clamping) | 710 void Element::scrollTo(const ScrollToOptions& options, ScrollClamping clamping) |
713 { | 711 { |
714 // If the element is the root element and document is in quirks mode, termin
ate these steps. | 712 // If the element is the root element and document is in quirks mode, termin
ate these steps. |
715 // Note that WebKit always uses quirks mode document scrolling behavior. See
Document::scrollingElement(). | 713 // Note that WebKit always uses quirks mode document scrolling behavior. See
Document::scrollingElement(). |
716 if (this == document().documentElement()) | 714 if (this == document().documentElement()) |
717 return; | 715 return; |
718 | 716 |
719 document().updateLayoutIgnorePendingStylesheets(); | 717 document().updateLayoutIgnorePendingStylesheets(); |
720 | 718 |
721 // If the element does not have any associated CSS layout box, the element h
as no associated scrolling box, | 719 // If the element does not have any associated CSS layout box, the element h
as no associated scrolling box, |
722 // or the element has no overflow, terminate these steps. | 720 // or the element has no overflow, terminate these steps. |
723 RenderBox* renderer = renderBox(); | 721 RenderBox* renderer = renderBox(); |
724 if (!renderer || !renderer->hasOverflowClip()) | 722 if (!renderer || !renderer->hasOverflowClip()) |
725 return; | 723 return; |
726 | 724 |
727 // Normalize non-finite values for left and top dictionary members of option
s, if present. | 725 ScrollToOptions scrollToOptions = normalizeNonFiniteCoordinatesOrFallBackTo(
options, |
728 double x = options.left ? normalizeNonFiniteValue(options.left.value()) : ad
justForAbsoluteZoom(renderer->scrollLeft(), *renderer); | 726 adjustForAbsoluteZoom(renderer->scrollLeft(), *renderer), |
729 double y = options.top ? normalizeNonFiniteValue(options.top.value()) : adju
stForAbsoluteZoom(renderer->scrollTop(), *renderer); | 727 adjustForAbsoluteZoom(renderer->scrollTop(), *renderer) |
730 | 728 ); |
731 renderer->setScrollLeft(clampToInteger(x * renderer->style().effectiveZoom()
), clamping); | 729 renderer->setScrollLeft(clampToInteger(scrollToOptions.left.value() * render
er->style().effectiveZoom()), clamping); |
732 renderer->setScrollTop(clampToInteger(y * renderer->style().effectiveZoom())
, clamping); | 730 renderer->setScrollTop(clampToInteger(scrollToOptions.top.value() * renderer
->style().effectiveZoom()), clamping); |
733 } | 731 } |
734 | 732 |
735 void Element::scrollTo(double x, double y) | 733 void Element::scrollTo(double x, double y) |
736 { | 734 { |
737 scrollTo({ x, y }); | 735 scrollTo({ x, y }); |
738 } | 736 } |
739 | 737 |
740 void Element::scrollByUnits(int units, ScrollGranularity granularity) | 738 void Element::scrollByUnits(int units, ScrollGranularity granularity) |
741 { | 739 { |
742 document().updateLayoutIgnorePendingStylesheets(); | 740 document().updateLayoutIgnorePendingStylesheets(); |
(...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1259 return IntRect(); | 1257 return IntRect(); |
1260 } | 1258 } |
1261 ···· | 1259 ···· |
1262 IntRect Element::screenRect() const | 1260 IntRect Element::screenRect() const |
1263 { | 1261 { |
1264 if (RenderObject* renderer = this->renderer()) | 1262 if (RenderObject* renderer = this->renderer()) |
1265 return document().view()->contentsToScreen(renderer->absoluteBoundingBox
Rect()); | 1263 return document().view()->contentsToScreen(renderer->absoluteBoundingBox
Rect()); |
1266 return IntRect(); | 1264 return IntRect(); |
1267 } | 1265 } |
1268 | 1266 |
1269 const AtomicString& Element::getAttribute(const AtomicString& localName) const | 1267 const AtomicString& Element::getAttribute(const AtomicString& qualifiedName) con
st |
1270 { | 1268 { |
1271 if (!elementData()) | 1269 if (!elementData()) |
1272 return nullAtom(); | 1270 return nullAtom(); |
1273 synchronizeAttribute(localName); | 1271 synchronizeAttribute(qualifiedName); |
1274 if (const Attribute* attribute = elementData()->findAttributeByName(localNam
e, shouldIgnoreAttributeCase(*this))) | 1272 if (const Attribute* attribute = elementData()->findAttributeByName(qualifie
dName, shouldIgnoreAttributeCase(*this))) |
1275 return attribute->value(); | 1273 return attribute->value(); |
1276 return nullAtom(); | 1274 return nullAtom(); |
1277 } | 1275 } |
1278 | 1276 |
1279 const AtomicString& Element::getAttributeNS(const AtomicString& namespaceURI, co
nst AtomicString& localName) const | 1277 const AtomicString& Element::getAttributeNS(const AtomicString& namespaceURI, co
nst AtomicString& localName) const |
1280 { | 1278 { |
1281 return getAttribute(QualifiedName(nullAtom(), localName, namespaceURI)); | 1279 return getAttribute(QualifiedName(nullAtom(), localName, namespaceURI)); |
1282 } | 1280 } |
1283 | 1281 |
1284 // https://dom.spec.whatwg.org/#dom-element-toggleattribute | 1282 // https://dom.spec.whatwg.org/#dom-element-toggleattribute |
1285 ExceptionOr<bool> Element::toggleAttribute(const AtomicString& localName, std::o
ptional<bool> force) | 1283 ExceptionOr<bool> Element::toggleAttribute(const AtomicString& qualifiedName, st
d::optional<bool> force) |
1286 { | 1284 { |
1287 if (!Document::isValidName(localName)) | 1285 if (!Document::isValidName(qualifiedName)) |
1288 return Exception { InvalidCharacterError }; | 1286 return Exception { InvalidCharacterError }; |
1289 | 1287 |
1290 synchronizeAttribute(localName); | 1288 synchronizeAttribute(qualifiedName); |
1291 | 1289 |
1292 auto caseAdjustedLocalName = shouldIgnoreAttributeCase(*this) ? localName.co
nvertToASCIILowercase() : localName; | 1290 auto caseAdjustedQualifiedName = shouldIgnoreAttributeCase(*this) ? qualifie
dName.convertToASCIILowercase() : qualifiedName; |
1293 unsigned index = elementData() ? elementData()->findAttributeIndexByName(cas
eAdjustedLocalName, false) : ElementData::attributeNotFound; | 1291 unsigned index = elementData() ? elementData()->findAttributeIndexByName(cas
eAdjustedQualifiedName, false) : ElementData::attributeNotFound; |
1294 if (index == ElementData::attributeNotFound) { | 1292 if (index == ElementData::attributeNotFound) { |
1295 if (!force || *force) { | 1293 if (!force || *force) { |
1296 setAttributeInternal(index, QualifiedName { nullAtom(), caseAdjusted
LocalName, nullAtom() }, emptyString(), NotInSynchronizationOfLazyAttribute); | 1294 setAttributeInternal(index, QualifiedName { nullAtom(), caseAdjusted
QualifiedName, nullAtom() }, emptyString(), NotInSynchronizationOfLazyAttribute)
; |
1297 return true; | 1295 return true; |
1298 } | 1296 } |
1299 return false; | 1297 return false; |
1300 } | 1298 } |
1301 | 1299 |
1302 if (!force || !*force) { | 1300 if (!force || !*force) { |
1303 removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute); | 1301 removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute); |
1304 return false; | 1302 return false; |
1305 } | 1303 } |
1306 return true; | 1304 return true; |
1307 } | 1305 } |
1308 | 1306 |
1309 ExceptionOr<void> Element::setAttribute(const AtomicString& localName, const Ato
micString& value) | 1307 ExceptionOr<void> Element::setAttribute(const AtomicString& qualifiedName, const
AtomicString& value) |
1310 { | 1308 { |
1311 if (!Document::isValidName(localName)) | 1309 if (!Document::isValidName(qualifiedName)) |
1312 return Exception { InvalidCharacterError }; | 1310 return Exception { InvalidCharacterError }; |
1313 | 1311 |
1314 synchronizeAttribute(localName); | 1312 synchronizeAttribute(qualifiedName); |
1315 auto caseAdjustedLocalName = shouldIgnoreAttributeCase(*this) ? localName.co
nvertToASCIILowercase() : localName; | 1313 auto caseAdjustedQualifiedName = shouldIgnoreAttributeCase(*this) ? qualifie
dName.convertToASCIILowercase() : qualifiedName; |
1316 unsigned index = elementData() ? elementData()->findAttributeIndexByName(cas
eAdjustedLocalName, false) : ElementData::attributeNotFound; | 1314 unsigned index = elementData() ? elementData()->findAttributeIndexByName(cas
eAdjustedQualifiedName, false) : ElementData::attributeNotFound; |
1317 auto name = index != ElementData::attributeNotFound ? attributeAt(index).nam
e() : QualifiedName { nullAtom(), caseAdjustedLocalName, nullAtom() }; | 1315 auto name = index != ElementData::attributeNotFound ? attributeAt(index).nam
e() : QualifiedName { nullAtom(), caseAdjustedQualifiedName, nullAtom() }; |
1318 setAttributeInternal(index, name, value, NotInSynchronizationOfLazyAttribute
); | 1316 setAttributeInternal(index, name, value, NotInSynchronizationOfLazyAttribute
); |
1319 | 1317 |
1320 return { }; | 1318 return { }; |
1321 } | 1319 } |
1322 | 1320 |
1323 void Element::setAttribute(const QualifiedName& name, const AtomicString& value) | 1321 void Element::setAttribute(const QualifiedName& name, const AtomicString& value) |
1324 { | 1322 { |
1325 synchronizeAttribute(name); | 1323 synchronizeAttribute(name); |
1326 unsigned index = elementData() ? elementData()->findAttributeIndexByName(nam
e) : ElementData::attributeNotFound; | 1324 unsigned index = elementData() ? elementData()->findAttributeIndexByName(nam
e) : ElementData::attributeNotFound; |
1327 setAttributeInternal(index, name, value, NotInSynchronizationOfLazyAttribute
); | 1325 setAttributeInternal(index, name, value, NotInSynchronizationOfLazyAttribute
); |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1476 } | 1474 } |
1477 } | 1475 } |
1478 | 1476 |
1479 URL Element::absoluteLinkURL() const | 1477 URL Element::absoluteLinkURL() const |
1480 { | 1478 { |
1481 if (!isLink()) | 1479 if (!isLink()) |
1482 return URL(); | 1480 return URL(); |
1483 | 1481 |
1484 AtomicString linkAttribute; | 1482 AtomicString linkAttribute; |
1485 if (hasTagName(SVGNames::aTag)) | 1483 if (hasTagName(SVGNames::aTag)) |
1486 linkAttribute = getAttribute(XLinkNames::hrefAttr); | 1484 linkAttribute = getAttribute(SVGNames::hrefAttr, XLinkNames::hrefAttr); |
1487 else | 1485 else |
1488 linkAttribute = getAttribute(HTMLNames::hrefAttr); | 1486 linkAttribute = getAttribute(HTMLNames::hrefAttr); |
1489 | 1487 |
1490 if (linkAttribute.isEmpty()) | 1488 if (linkAttribute.isEmpty()) |
1491 return URL(); | 1489 return URL(); |
1492 | 1490 |
1493 return document().completeURL(stripLeadingAndTrailingHTMLSpaces(linkAttribut
e)); | 1491 return document().completeURL(stripLeadingAndTrailingHTMLSpaces(linkAttribut
e)); |
1494 } | 1492 } |
1495 | 1493 |
1496 #if ENABLE(TOUCH_EVENTS) | 1494 #if ENABLE(TOUCH_EVENTS) |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1646 ASSERT_WITH_SECURITY_IMPLICATION(&document() == &newDocument); | 1644 ASSERT_WITH_SECURITY_IMPLICATION(&document() == &newDocument); |
1647 | 1645 |
1648 if (oldDocument.inQuirksMode() != document().inQuirksMode()) { | 1646 if (oldDocument.inQuirksMode() != document().inQuirksMode()) { |
1649 // ElementData::m_classNames or ElementData::m_idForStyleResolution need
to be updated with the right case. | 1647 // ElementData::m_classNames or ElementData::m_idForStyleResolution need
to be updated with the right case. |
1650 if (hasID()) | 1648 if (hasID()) |
1651 attributeChanged(idAttr, nullAtom(), getIdAttribute()); | 1649 attributeChanged(idAttr, nullAtom(), getIdAttribute()); |
1652 if (hasClass()) | 1650 if (hasClass()) |
1653 attributeChanged(classAttr, nullAtom(), getAttribute(classAttr)); | 1651 attributeChanged(classAttr, nullAtom(), getAttribute(classAttr)); |
1654 } | 1652 } |
1655 | 1653 |
| 1654 // FIXME: Do we need to update newDocument's intersection observer targets? |
| 1655 |
1656 if (UNLIKELY(isDefinedCustomElement())) | 1656 if (UNLIKELY(isDefinedCustomElement())) |
1657 CustomElementReactionQueue::enqueueAdoptedCallbackIfNeeded(*this, oldDoc
ument, newDocument); | 1657 CustomElementReactionQueue::enqueueAdoptedCallbackIfNeeded(*this, oldDoc
ument, newDocument); |
1658 | 1658 |
1659 #if ENABLE(INTERSECTION_OBSERVER) | 1659 #if ENABLE(INTERSECTION_OBSERVER) |
1660 disconnectFromIntersectionObservers(); | 1660 if (auto* observerData = intersectionObserverData()) { |
| 1661 for (auto* observer : observerData->observers) { |
| 1662 if (oldDocument.deactivateIntersectionObserver(*observer)) |
| 1663 newDocument.activateIntersectionObserver(*observer); |
| 1664 } |
| 1665 } |
1661 #endif | 1666 #endif |
1662 } | 1667 } |
1663 | 1668 |
1664 bool Element::hasAttributes() const | 1669 bool Element::hasAttributes() const |
1665 { | 1670 { |
1666 synchronizeAllAttributes(); | 1671 synchronizeAllAttributes(); |
1667 return elementData() && elementData()->length(); | 1672 return elementData() && elementData()->length(); |
1668 } | 1673 } |
1669 | 1674 |
1670 bool Element::hasEquivalentAttributes(const Element* other) const | 1675 bool Element::hasEquivalentAttributes(const Element* other) const |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1753 if (newDocument) | 1758 if (newDocument) |
1754 updateNameForDocument(*newDocument, nullAtom(), nameValue); | 1759 updateNameForDocument(*newDocument, nullAtom(), nameValue); |
1755 } | 1760 } |
1756 | 1761 |
1757 if (newScope && hasTagName(labelTag)) { | 1762 if (newScope && hasTagName(labelTag)) { |
1758 if (newScope->shouldCacheLabelsByForAttribute()) | 1763 if (newScope->shouldCacheLabelsByForAttribute()) |
1759 updateLabel(*newScope, nullAtom(), attributeWithoutSynchronization(f
orAttr)); | 1764 updateLabel(*newScope, nullAtom(), attributeWithoutSynchronization(f
orAttr)); |
1760 } | 1765 } |
1761 | 1766 |
1762 if (becomeConnected) { | 1767 if (becomeConnected) { |
1763 if (UNLIKELY(isCustomElementUpgradeCandidate())) | 1768 if (UNLIKELY(isCustomElementUpgradeCandidate())) { |
| 1769 ASSERT(isConnected()); |
1764 CustomElementReactionQueue::enqueueElementUpgradeIfDefined(*this); | 1770 CustomElementReactionQueue::enqueueElementUpgradeIfDefined(*this); |
| 1771 } |
1765 if (UNLIKELY(isDefinedCustomElement())) | 1772 if (UNLIKELY(isDefinedCustomElement())) |
1766 CustomElementReactionQueue::enqueueConnectedCallbackIfNeeded(*this); | 1773 CustomElementReactionQueue::enqueueConnectedCallbackIfNeeded(*this); |
1767 } | 1774 } |
| 1775 |
| 1776 if (UNLIKELY(hasTagName(articleTag) && newDocument)) |
| 1777 newDocument->registerArticleElement(*this); |
1768 | 1778 |
1769 return InsertedIntoAncestorResult::Done; | 1779 return InsertedIntoAncestorResult::Done; |
1770 } | 1780 } |
1771 | 1781 |
1772 void Element::removedFromAncestor(RemovalType removalType, ContainerNode& oldPar
entOfRemovedTree) | 1782 void Element::removedFromAncestor(RemovalType removalType, ContainerNode& oldPar
entOfRemovedTree) |
1773 { | 1783 { |
1774 #if ENABLE(FULLSCREEN_API) | 1784 #if ENABLE(FULLSCREEN_API) |
1775 if (containsFullScreenElement()) | 1785 if (containsFullScreenElement()) |
1776 setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false); | 1786 setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false); |
1777 #endif | 1787 #endif |
(...skipping 28 matching lines...) Expand all Loading... |
1806 } | 1816 } |
1807 | 1817 |
1808 if (oldScope && hasTagName(labelTag)) { | 1818 if (oldScope && hasTagName(labelTag)) { |
1809 if (oldScope->shouldCacheLabelsByForAttribute()) | 1819 if (oldScope->shouldCacheLabelsByForAttribute()) |
1810 updateLabel(*oldScope, attributeWithoutSynchronization(forAttr),
nullAtom()); | 1820 updateLabel(*oldScope, attributeWithoutSynchronization(forAttr),
nullAtom()); |
1811 } | 1821 } |
1812 | 1822 |
1813 if (oldDocument) { | 1823 if (oldDocument) { |
1814 if (oldDocument->cssTarget() == this) | 1824 if (oldDocument->cssTarget() == this) |
1815 oldDocument->setCSSTarget(nullptr); | 1825 oldDocument->setCSSTarget(nullptr); |
| 1826 if (UNLIKELY(hasTagName(articleTag))) |
| 1827 oldDocument->unregisterArticleElement(*this); |
1816 } | 1828 } |
1817 | 1829 |
1818 if (removalType.disconnectedFromDocument && UNLIKELY(isDefinedCustomElem
ent())) | 1830 if (removalType.disconnectedFromDocument && UNLIKELY(isDefinedCustomElem
ent())) |
1819 CustomElementReactionQueue::enqueueDisconnectedCallbackIfNeeded(*thi
s); | 1831 CustomElementReactionQueue::enqueueDisconnectedCallbackIfNeeded(*thi
s); |
1820 } | 1832 } |
1821 | 1833 |
1822 if (!parentNode()) { | 1834 if (!parentNode()) { |
1823 if (auto* shadowRoot = oldParentOfRemovedTree.shadowRoot()) | 1835 if (auto* shadowRoot = oldParentOfRemovedTree.shadowRoot()) |
1824 shadowRoot->hostChildElementDidChange(*this); | 1836 shadowRoot->hostChildElementDidChange(*this); |
1825 } | 1837 } |
1826 | 1838 |
1827 clearBeforePseudoElement(); | 1839 clearBeforePseudoElement(); |
1828 clearAfterPseudoElement(); | 1840 clearAfterPseudoElement(); |
1829 | 1841 |
1830 ContainerNode::removedFromAncestor(removalType, oldParentOfRemovedTree); | 1842 ContainerNode::removedFromAncestor(removalType, oldParentOfRemovedTree); |
1831 | 1843 |
1832 if (hasPendingResources()) | 1844 if (hasPendingResources()) |
1833 document().accessSVGExtensions().removeElementFromPendingResources(this)
; | 1845 document().accessSVGExtensions().removeElementFromPendingResources(this)
; |
1834 | 1846 |
1835 RefPtr<Frame> frame = document().frame(); | 1847 RefPtr<Frame> frame = document().frame(); |
1836 if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnab
led()) { | 1848 if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnab
led()) { |
1837 if (auto* timeline = document().existingTimeline()) | 1849 if (auto* timeline = document().existingTimeline()) |
1838 timeline->removeAnimationsForElement(*this); | 1850 timeline->elementWasRemoved(*this); |
1839 } else if (frame) | 1851 } else if (frame) |
1840 frame->animation().cancelAnimations(*this); | 1852 frame->animation().cancelAnimations(*this); |
1841 | 1853 |
1842 #if PLATFORM(MAC) | 1854 #if PLATFORM(MAC) |
1843 if (frame && frame->page()) | 1855 if (frame && frame->page()) |
1844 frame->page()->removeLatchingStateForTarget(*this); | 1856 frame->page()->removeLatchingStateForTarget(*this); |
1845 #endif | 1857 #endif |
1846 } | 1858 } |
1847 | 1859 |
1848 ShadowRoot* Element::shadowRoot() const | 1860 ShadowRoot* Element::shadowRoot() const |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2008 } | 2020 } |
2009 | 2021 |
2010 void Element::enqueueToUpgrade(JSCustomElementInterface& elementInterface) | 2022 void Element::enqueueToUpgrade(JSCustomElementInterface& elementInterface) |
2011 { | 2023 { |
2012 ASSERT(!isDefinedCustomElement() && !isFailedCustomElement()); | 2024 ASSERT(!isDefinedCustomElement() && !isFailedCustomElement()); |
2013 setFlag(IsCustomElement); | 2025 setFlag(IsCustomElement); |
2014 setFlag(IsEditingTextOrUndefinedCustomElementFlag); | 2026 setFlag(IsEditingTextOrUndefinedCustomElementFlag); |
2015 InspectorInstrumentation::didChangeCustomElementState(*this); | 2027 InspectorInstrumentation::didChangeCustomElementState(*this); |
2016 | 2028 |
2017 auto& data = ensureElementRareData(); | 2029 auto& data = ensureElementRareData(); |
2018 ASSERT(!data.customElementReactionQueue()); | 2030 bool alreadyScheduledToUpgrade = data.customElementReactionQueue(); |
2019 | 2031 if (!alreadyScheduledToUpgrade) |
2020 data.setCustomElementReactionQueue(std::make_unique<CustomElementReactionQue
ue>(elementInterface)); | 2032 data.setCustomElementReactionQueue(std::make_unique<CustomElementReactio
nQueue>(elementInterface)); |
2021 data.customElementReactionQueue()->enqueueElementUpgrade(*this); | 2033 data.customElementReactionQueue()->enqueueElementUpgrade(*this, alreadySched
uledToUpgrade); |
2022 } | 2034 } |
2023 | 2035 |
2024 CustomElementReactionQueue* Element::reactionQueue() const | 2036 CustomElementReactionQueue* Element::reactionQueue() const |
2025 { | 2037 { |
2026 ASSERT(isDefinedCustomElement() || isCustomElementUpgradeCandidate()); | 2038 ASSERT(isDefinedCustomElement() || isCustomElementUpgradeCandidate()); |
2027 if (!hasRareData()) | 2039 if (!hasRareData()) |
2028 return nullptr; | 2040 return nullptr; |
2029 return elementRareData()->customElementReactionQueue(); | 2041 return elementRareData()->customElementReactionQueue(); |
2030 } | 2042 } |
2031 | 2043 |
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2419 } | 2431 } |
2420 | 2432 |
2421 willModifyAttribute(name, nullAtom(), value); | 2433 willModifyAttribute(name, nullAtom(), value); |
2422 { | 2434 { |
2423 Style::AttributeChangeInvalidation styleInvalidation(*this, name, nullAt
om(), value); | 2435 Style::AttributeChangeInvalidation styleInvalidation(*this, name, nullAt
om(), value); |
2424 ensureUniqueElementData().addAttribute(name, value); | 2436 ensureUniqueElementData().addAttribute(name, value); |
2425 } | 2437 } |
2426 didAddAttribute(name, value); | 2438 didAddAttribute(name, value); |
2427 } | 2439 } |
2428 | 2440 |
2429 bool Element::removeAttribute(const AtomicString& name) | 2441 bool Element::removeAttribute(const AtomicString& qualifiedName) |
2430 { | 2442 { |
2431 if (!elementData()) | 2443 if (!elementData()) |
2432 return false; | 2444 return false; |
2433 | 2445 |
2434 AtomicString localName = shouldIgnoreAttributeCase(*this) ? name.convertToAS
CIILowercase() : name; | 2446 AtomicString caseAdjustedQualifiedName = shouldIgnoreAttributeCase(*this) ?
qualifiedName.convertToASCIILowercase() : qualifiedName; |
2435 unsigned index = elementData()->findAttributeIndexByName(localName, false); | 2447 unsigned index = elementData()->findAttributeIndexByName(caseAdjustedQualifi
edName, false); |
2436 if (index == ElementData::attributeNotFound) { | 2448 if (index == ElementData::attributeNotFound) { |
2437 if (UNLIKELY(localName == styleAttr) && elementData()->styleAttributeIsD
irty() && is<StyledElement>(*this)) | 2449 if (UNLIKELY(caseAdjustedQualifiedName == styleAttr) && elementData()->s
tyleAttributeIsDirty() && is<StyledElement>(*this)) |
2438 downcast<StyledElement>(*this).removeAllInlineStyleProperties(); | 2450 downcast<StyledElement>(*this).removeAllInlineStyleProperties(); |
2439 return false; | 2451 return false; |
2440 } | 2452 } |
2441 | 2453 |
2442 removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute); | 2454 removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute); |
2443 return true; | 2455 return true; |
2444 } | 2456 } |
2445 | 2457 |
2446 bool Element::removeAttributeNS(const AtomicString& namespaceURI, const AtomicSt
ring& localName) | 2458 bool Element::removeAttributeNS(const AtomicString& namespaceURI, const AtomicSt
ring& localName) |
2447 { | 2459 { |
2448 return removeAttribute(QualifiedName(nullAtom(), localName, namespaceURI)); | 2460 return removeAttribute(QualifiedName(nullAtom(), localName, namespaceURI)); |
2449 } | 2461 } |
2450 | 2462 |
2451 RefPtr<Attr> Element::getAttributeNode(const AtomicString& localName) | 2463 RefPtr<Attr> Element::getAttributeNode(const AtomicString& qualifiedName) |
2452 { | 2464 { |
2453 if (!elementData()) | 2465 if (!elementData()) |
2454 return nullptr; | 2466 return nullptr; |
2455 synchronizeAttribute(localName); | 2467 synchronizeAttribute(qualifiedName); |
2456 const Attribute* attribute = elementData()->findAttributeByName(localName, s
houldIgnoreAttributeCase(*this)); | 2468 const Attribute* attribute = elementData()->findAttributeByName(qualifiedNam
e, shouldIgnoreAttributeCase(*this)); |
2457 if (!attribute) | 2469 if (!attribute) |
2458 return nullptr; | 2470 return nullptr; |
2459 return ensureAttr(attribute->name()); | 2471 return ensureAttr(attribute->name()); |
2460 } | 2472 } |
2461 | 2473 |
2462 RefPtr<Attr> Element::getAttributeNodeNS(const AtomicString& namespaceURI, const
AtomicString& localName) | 2474 RefPtr<Attr> Element::getAttributeNodeNS(const AtomicString& namespaceURI, const
AtomicString& localName) |
2463 { | 2475 { |
2464 if (!elementData()) | 2476 if (!elementData()) |
2465 return 0; | 2477 return 0; |
2466 QualifiedName qName(nullAtom(), localName, namespaceURI); | 2478 QualifiedName qName(nullAtom(), localName, namespaceURI); |
2467 synchronizeAttribute(qName); | 2479 synchronizeAttribute(qName); |
2468 const Attribute* attribute = elementData()->findAttributeByName(qName); | 2480 const Attribute* attribute = elementData()->findAttributeByName(qName); |
2469 if (!attribute) | 2481 if (!attribute) |
2470 return 0; | 2482 return 0; |
2471 return ensureAttr(attribute->name()); | 2483 return ensureAttr(attribute->name()); |
2472 } | 2484 } |
2473 | 2485 |
2474 bool Element::hasAttribute(const AtomicString& localName) const | 2486 bool Element::hasAttribute(const AtomicString& qualifiedName) const |
2475 { | 2487 { |
2476 if (!elementData()) | 2488 if (!elementData()) |
2477 return false; | 2489 return false; |
2478 synchronizeAttribute(localName); | 2490 synchronizeAttribute(qualifiedName); |
2479 return elementData()->findAttributeByName(localName, shouldIgnoreAttributeCa
se(*this)); | 2491 return elementData()->findAttributeByName(qualifiedName, shouldIgnoreAttribu
teCase(*this)); |
2480 } | 2492 } |
2481 | 2493 |
2482 bool Element::hasAttributeNS(const AtomicString& namespaceURI, const AtomicStrin
g& localName) const | 2494 bool Element::hasAttributeNS(const AtomicString& namespaceURI, const AtomicStrin
g& localName) const |
2483 { | 2495 { |
2484 if (!elementData()) | 2496 if (!elementData()) |
2485 return false; | 2497 return false; |
2486 QualifiedName qName(nullAtom(), localName, namespaceURI); | 2498 QualifiedName qName(nullAtom(), localName, namespaceURI); |
2487 synchronizeAttribute(qName); | 2499 synchronizeAttribute(qName); |
2488 return elementData()->findAttributeByName(qName); | 2500 return elementData()->findAttributeByName(qName); |
2489 } | 2501 } |
(...skipping 747 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3237 void Element::requestPointerLock() | 3249 void Element::requestPointerLock() |
3238 { | 3250 { |
3239 if (document().page()) | 3251 if (document().page()) |
3240 document().page()->pointerLockController().requestPointerLock(this); | 3252 document().page()->pointerLockController().requestPointerLock(this); |
3241 } | 3253 } |
3242 #endif | 3254 #endif |
3243 | 3255 |
3244 #if ENABLE(INTERSECTION_OBSERVER) | 3256 #if ENABLE(INTERSECTION_OBSERVER) |
3245 void Element::startObservingIntersections(IntersectionObserver& observer) | 3257 void Element::startObservingIntersections(IntersectionObserver& observer) |
3246 { | 3258 { |
3247 auto& data = ensureElementRareData(); | 3259 auto* trackingDocument = observer.trackingDocument(); |
3248 | 3260 if (!trackingDocument) |
3249 auto* registrations = data.intersectionObserverRegistrations(); | 3261 return; |
3250 if (!registrations) { | 3262 auto& observerData = ensureIntersectionObserverData(); |
3251 data.setIntersectionObserverRegistrations(std::make_unique<Vector<Inters
ectionObserverRegistration>>()); | 3263 auto& registrations = observerData.registrations; |
3252 registrations = data.intersectionObserverRegistrations(); | |
3253 } | |
3254 | 3264 |
3255 // If target is in this's internal [[ObservationTargets]] slot, return. | 3265 // If target is in this's internal [[ObservationTargets]] slot, return. |
3256 for (auto& registration : *registrations) { | 3266 for (auto& registration : registrations) { |
3257 if (registration.observer == &observer) | 3267 if (registration.observer == &observer) |
3258 return; | 3268 return; |
3259 } | 3269 } |
3260 | 3270 |
3261 // Let intersectionObserverRegistration be an IntersectionObserverRegistrati
on record with an observer | 3271 // Let intersectionObserverRegistration be an IntersectionObserverRegistrati
on record with an observer |
3262 // property set to this and a previousThreshold property set so that it's im
mediately differently from | 3272 // property set to this and a previousThreshold property set so that it's im
mediately differently from |
3263 // the current threshold, triggering an initial notification. | 3273 // the current threshold, triggering an initial notification. |
3264 // Append intersectionObserverRegistration to targets internal [[RegisteredI
ntersectionObservers]] slot. | 3274 // Append intersectionObserverRegistration to targets internal [[RegisteredI
ntersectionObservers]] slot. |
3265 registrations->append({ &observer, std::numeric_limits<size_t>::max(), false
}); | 3275 registrations.append({ &observer, std::numeric_limits<size_t>::max(), false
}); |
3266 | 3276 |
3267 // Add target to this's internal [[ObservationTargets]] slot. | 3277 // Add target to this's internal [[ObservationTargets]] slot. |
3268 observer.addObservationTarget(*this); | 3278 observer.addObservationTarget(*this); |
3269 | |
3270 document().addToIntersectionObserverTargets(*this); | |
3271 document().postTask([&document = document()] (ScriptExecutionContext&) mutab
le { | |
3272 document.updateIntersectionObservations(); | |
3273 }); | |
3274 | |
3275 } | 3279 } |
3276 | 3280 |
3277 void Element::endObservingIntersections(IntersectionObserver& observer) | 3281 void Element::endObservingIntersections(IntersectionObserver& observer) |
3278 { | 3282 { |
3279 // Remove the IntersectionObserverRegistration record whose observer propert
y is equal to this from | 3283 // Remove the IntersectionObserverRegistration record whose observer propert
y is equal to this from |
3280 // targets internal [[RegisteredIntersectionObservers]] slot. | 3284 // targets internal [[RegisteredIntersectionObservers]] slot. |
3281 auto* registrations = hasRareData() ? elementRareData()->intersectionObserve
rRegistrations() : nullptr; | 3285 auto* observerData = hasRareData() ? elementRareData()->intersectionObserver
Data() : nullptr; |
3282 if (!registrations) { | 3286 if (!observerData) { |
3283 ASSERT(!observer.hasObservationTarget(*this)); | 3287 ASSERT(!observer.hasObservationTarget(*this)); |
3284 return; | 3288 return; |
3285 } | 3289 } |
3286 | 3290 |
3287 for (size_t i = 0; i < registrations->size(); ++i) { | 3291 auto& registrations = observerData->registrations; |
3288 auto& observerRegistration = registrations->at(i); | 3292 |
| 3293 for (size_t i = 0; i < registrations.size(); ++i) { |
| 3294 auto& observerRegistration = registrations.at(i); |
3289 if (observerRegistration.observer == &observer) { | 3295 if (observerRegistration.observer == &observer) { |
3290 registrations->remove(i); | 3296 registrations.remove(i); |
3291 break; | 3297 break; |
3292 } | 3298 } |
3293 } | 3299 } |
3294 | 3300 |
3295 // Remove target from this's internal [[ObservationTargets]] slot. | 3301 // Remove target from this's internal [[ObservationTargets]] slot. |
3296 observer.removeObservationTarget(*this); | 3302 observer.removeObservationTarget(*this); |
3297 | |
3298 if (registrations->isEmpty()) | |
3299 document().removeFromIntersectionObserverTargets(*this); | |
3300 } | 3303 } |
3301 | 3304 |
3302 void Element::disconnectFromIntersectionObservers() | 3305 void Element::disconnectFromIntersectionObservers() |
3303 { | 3306 { |
3304 auto* registrations = hasRareData() ? elementRareData()->intersectionObserve
rRegistrations() : nullptr; | 3307 auto* observerData = intersectionObserverData(); |
3305 if (registrations) { | 3308 if (!observerData) |
3306 for (auto& registration : *registrations) | 3309 return; |
3307 registration.observer->removeObservationTarget(*this); | 3310 |
3308 } | 3311 for (auto& registration : observerData->registrations) |
3309 | 3312 registration.observer->removeObservationTarget(*this); |
3310 document().removeFromIntersectionObserverTargets(*this); | 3313 observerData->registrations.clear(); |
3311 } | 3314 |
3312 | 3315 for (auto* observer : observerData->observers) |
3313 Vector<IntersectionObserverRegistration>* Element::intersectionObserverRegistrat
ions() | 3316 observer->rootDestroyed(); |
3314 { | 3317 observerData->observers.clear(); |
3315 return hasRareData() ? elementRareData()->intersectionObserverRegistrations(
) : nullptr; | 3318 } |
| 3319 |
| 3320 IntersectionObserverData& Element::ensureIntersectionObserverData() |
| 3321 { |
| 3322 auto& data = ensureElementRareData(); |
| 3323 if (!data.intersectionObserverData()) |
| 3324 data.setIntersectionObserverData(std::make_unique<IntersectionObserverDa
ta>()); |
| 3325 return *data.intersectionObserverData(); |
| 3326 } |
| 3327 |
| 3328 IntersectionObserverData* Element::intersectionObserverData() |
| 3329 { |
| 3330 return hasRareData() ? elementRareData()->intersectionObserverData() : nullp
tr; |
3316 } | 3331 } |
3317 #endif | 3332 #endif |
3318 | 3333 |
3319 SpellcheckAttributeState Element::spellcheckAttributeState() const | 3334 SpellcheckAttributeState Element::spellcheckAttributeState() const |
3320 { | 3335 { |
3321 const AtomicString& value = attributeWithoutSynchronization(HTMLNames::spell
checkAttr); | 3336 const AtomicString& value = attributeWithoutSynchronization(HTMLNames::spell
checkAttr); |
3322 if (value.isNull()) | 3337 if (value.isNull()) |
3323 return SpellcheckAttributeDefault; | 3338 return SpellcheckAttributeDefault; |
3324 if (value.isEmpty() || equalLettersIgnoringASCIICase(value, "true")) | 3339 if (value.isEmpty() || equalLettersIgnoringASCIICase(value, "true")) |
3325 return SpellcheckAttributeTrue; | 3340 return SpellcheckAttributeTrue; |
(...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3948 if (auto timeline = document().existingTimeline()) { | 3963 if (auto timeline = document().existingTimeline()) { |
3949 for (auto& animation : timeline->animationsForElement(*this, AnimationTi
meline::Ordering::Sorted)) { | 3964 for (auto& animation : timeline->animationsForElement(*this, AnimationTi
meline::Ordering::Sorted)) { |
3950 if (animation->canBeListed()) | 3965 if (animation->canBeListed()) |
3951 animations.append(animation); | 3966 animations.append(animation); |
3952 } | 3967 } |
3953 } | 3968 } |
3954 return animations; | 3969 return animations; |
3955 } | 3970 } |
3956 | 3971 |
3957 } // namespace WebCore | 3972 } // namespace WebCore |
LEFT | RIGHT |