Use Optional::valueOr() instead of Optional::value_or()
[WebKit-https.git] / Source / WebCore / dom / Element.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2001 Peter Kelly (pmk@post.com)
5  *           (C) 2001 Dirk Mueller (mueller@kde.org)
6  *           (C) 2007 David Smith (catfish.man@gmail.com)
7  * Copyright (C) 2004-2017 Apple Inc. All rights reserved.
8  *           (C) 2007 Eric Seidel (eric@webkit.org)
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public License
21  * along with this library; see the file COPYING.LIB.  If not, write to
22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  */
25
26 #include "config.h"
27 #include "Element.h"
28
29 #include "AXObjectCache.h"
30 #include "Attr.h"
31 #include "AttributeChangeInvalidation.h"
32 #include "CSSAnimationController.h"
33 #include "CSSParser.h"
34 #include "Chrome.h"
35 #include "ChromeClient.h"
36 #include "ClassChangeInvalidation.h"
37 #include "ComposedTreeAncestorIterator.h"
38 #include "ContainerNodeAlgorithms.h"
39 #include "CustomElementReactionQueue.h"
40 #include "CustomElementRegistry.h"
41 #include "DOMRect.h"
42 #include "DOMRectList.h"
43 #include "DOMTokenList.h"
44 #include "DOMWindow.h"
45 #include "DocumentSharedObjectPool.h"
46 #include "DocumentTimeline.h"
47 #include "Editing.h"
48 #include "ElementIterator.h"
49 #include "ElementRareData.h"
50 #include "EventDispatcher.h"
51 #include "EventHandler.h"
52 #include "EventNames.h"
53 #include "FocusController.h"
54 #include "FocusEvent.h"
55 #include "Frame.h"
56 #include "FrameSelection.h"
57 #include "FrameView.h"
58 #include "HTMLBodyElement.h"
59 #include "HTMLCanvasElement.h"
60 #include "HTMLCollection.h"
61 #include "HTMLDocument.h"
62 #include "HTMLHtmlElement.h"
63 #include "HTMLLabelElement.h"
64 #include "HTMLNameCollection.h"
65 #include "HTMLObjectElement.h"
66 #include "HTMLOptGroupElement.h"
67 #include "HTMLOptionElement.h"
68 #include "HTMLParserIdioms.h"
69 #include "HTMLSelectElement.h"
70 #include "HTMLTemplateElement.h"
71 #include "IdChangeInvalidation.h"
72 #include "IdTargetObserverRegistry.h"
73 #include "InspectorInstrumentation.h"
74 #include "JSLazyEventListener.h"
75 #include "KeyboardEvent.h"
76 #include "KeyframeEffect.h"
77 #include "MutationObserverInterestGroup.h"
78 #include "MutationRecord.h"
79 #include "NodeRenderStyle.h"
80 #include "PlatformWheelEvent.h"
81 #include "PointerLockController.h"
82 #include "RenderFragmentContainer.h"
83 #include "RenderLayer.h"
84 #include "RenderListBox.h"
85 #include "RenderTheme.h"
86 #include "RenderTreeUpdater.h"
87 #include "RenderView.h"
88 #include "RenderWidget.h"
89 #include "RuntimeEnabledFeatures.h"
90 #include "SVGDocumentExtensions.h"
91 #include "SVGElement.h"
92 #include "SVGNames.h"
93 #include "SVGSVGElement.h"
94 #include "ScriptDisallowedScope.h"
95 #include "ScrollIntoViewOptions.h"
96 #include "ScrollLatchingState.h"
97 #include "SelectorQuery.h"
98 #include "Settings.h"
99 #include "SimulatedClick.h"
100 #include "SlotAssignment.h"
101 #include "StyleProperties.h"
102 #include "StyleResolver.h"
103 #include "StyleScope.h"
104 #include "StyleTreeResolver.h"
105 #include "TextIterator.h"
106 #include "VoidCallback.h"
107 #include "WebAnimation.h"
108 #include "WheelEvent.h"
109 #include "XLinkNames.h"
110 #include "XMLNSNames.h"
111 #include "XMLNames.h"
112 #include "markup.h"
113 #include <wtf/IsoMallocInlines.h>
114 #include <wtf/NeverDestroyed.h>
115 #include <wtf/text/CString.h>
116
117 namespace WebCore {
118
119 WTF_MAKE_ISO_ALLOCATED_IMPL(Element);
120
121 using namespace HTMLNames;
122 using namespace XMLNames;
123
124 static HashMap<Element*, Vector<RefPtr<Attr>>>& attrNodeListMap()
125 {
126     static NeverDestroyed<HashMap<Element*, Vector<RefPtr<Attr>>>> map;
127     return map;
128 }
129
130 static Vector<RefPtr<Attr>>* attrNodeListForElement(Element& element)
131 {
132     if (!element.hasSyntheticAttrChildNodes())
133         return nullptr;
134     ASSERT(attrNodeListMap().contains(&element));
135     return &attrNodeListMap().find(&element)->value;
136 }
137
138 static Vector<RefPtr<Attr>>& ensureAttrNodeListForElement(Element& element)
139 {
140     if (element.hasSyntheticAttrChildNodes()) {
141         ASSERT(attrNodeListMap().contains(&element));
142         return attrNodeListMap().find(&element)->value;
143     }
144     ASSERT(!attrNodeListMap().contains(&element));
145     element.setHasSyntheticAttrChildNodes(true);
146     return attrNodeListMap().add(&element, Vector<RefPtr<Attr>>()).iterator->value;
147 }
148
149 static void removeAttrNodeListForElement(Element& element)
150 {
151     ASSERT(element.hasSyntheticAttrChildNodes());
152     ASSERT(attrNodeListMap().contains(&element));
153     attrNodeListMap().remove(&element);
154     element.setHasSyntheticAttrChildNodes(false);
155 }
156
157 static Attr* findAttrNodeInList(Vector<RefPtr<Attr>>& attrNodeList, const QualifiedName& name)
158 {
159     for (auto& node : attrNodeList) {
160         if (node->qualifiedName().matches(name))
161             return node.get();
162     }
163     return nullptr;
164 }
165
166 static Attr* findAttrNodeInList(Vector<RefPtr<Attr>>& attrNodeList, const AtomicString& localName, bool shouldIgnoreAttributeCase)
167 {
168     const AtomicString& caseAdjustedName = shouldIgnoreAttributeCase ? localName.convertToASCIILowercase() : localName;
169     for (auto& node : attrNodeList) {
170         if (node->qualifiedName().localName() == caseAdjustedName)
171             return node.get();
172     }
173     return nullptr;
174 }
175
176 Ref<Element> Element::create(const QualifiedName& tagName, Document& document)
177 {
178     return adoptRef(*new Element(tagName, document, CreateElement));
179 }
180
181 Element::Element(const QualifiedName& tagName, Document& document, ConstructionType type)
182     : ContainerNode(document, type)
183     , m_tagName(tagName)
184 {
185 }
186
187 Element::~Element()
188 {
189     ASSERT(!beforePseudoElement());
190     ASSERT(!afterPseudoElement());
191
192 #if ENABLE(INTERSECTION_OBSERVER)
193     disconnectFromIntersectionObservers();
194 #endif
195
196     removeShadowRoot();
197
198     if (hasSyntheticAttrChildNodes())
199         detachAllAttrNodesFromElement();
200
201     if (hasPendingResources()) {
202         document().accessSVGExtensions().removeElementFromPendingResources(this);
203         ASSERT(!hasPendingResources());
204     }
205 }
206
207 inline ElementRareData* Element::elementRareData() const
208 {
209     ASSERT_WITH_SECURITY_IMPLICATION(hasRareData());
210     return static_cast<ElementRareData*>(rareData());
211 }
212
213 inline ElementRareData& Element::ensureElementRareData()
214 {
215     return static_cast<ElementRareData&>(ensureRareData());
216 }
217
218 void Element::clearTabIndexExplicitlyIfNeeded()
219 {
220     if (hasRareData())
221         elementRareData()->clearTabIndexExplicitly();
222 }
223
224 void Element::setTabIndexExplicitly(int tabIndex)
225 {
226     ensureElementRareData().setTabIndexExplicitly(tabIndex);
227 }
228
229 bool Element::tabIndexSetExplicitly() const
230 {
231     return hasRareData() && elementRareData()->tabIndexSetExplicitly();
232 }
233
234 bool Element::supportsFocus() const
235 {
236     return tabIndexSetExplicitly();
237 }
238
239 RefPtr<Element> Element::focusDelegate()
240 {
241     return this;
242 }
243
244 int Element::tabIndex() const
245 {
246     return hasRareData() ? elementRareData()->tabIndex() : 0;
247 }
248
249 void Element::setTabIndex(int value)
250 {
251     setIntegralAttribute(tabindexAttr, value);
252 }
253
254 bool Element::isKeyboardFocusable(KeyboardEvent*) const
255 {
256     return isFocusable() && tabIndex() >= 0;
257 }
258
259 bool Element::isMouseFocusable() const
260 {
261     return isFocusable();
262 }
263
264 bool Element::shouldUseInputMethod()
265 {
266     return computeEditability(UserSelectAllIsAlwaysNonEditable, ShouldUpdateStyle::Update) != Editability::ReadOnly;
267 }
268
269 static bool isForceEvent(const PlatformMouseEvent& platformEvent)
270 {
271     return platformEvent.type() == PlatformEvent::MouseForceChanged || platformEvent.type() == PlatformEvent::MouseForceDown || platformEvent.type() == PlatformEvent::MouseForceUp;
272 }
273
274 bool Element::dispatchMouseEvent(const PlatformMouseEvent& platformEvent, const AtomicString& eventType, int detail, Element* relatedTarget)
275 {
276     if (isDisabledFormControl())
277         return false;
278
279     if (isForceEvent(platformEvent) && !document().hasListenerTypeForEventType(platformEvent.type()))
280         return false;
281
282     Ref<MouseEvent> mouseEvent = MouseEvent::create(eventType, document().windowProxy(), platformEvent, detail, relatedTarget);
283
284     if (mouseEvent->type().isEmpty())
285         return true; // Shouldn't happen.
286
287     ASSERT(!mouseEvent->target() || mouseEvent->target() != relatedTarget);
288     dispatchEvent(mouseEvent);
289     bool didNotSwallowEvent = !mouseEvent->defaultPrevented() && !mouseEvent->defaultHandled();
290
291     if (mouseEvent->type() == eventNames().clickEvent && mouseEvent->detail() == 2) {
292         // Special case: If it's a double click event, we also send the dblclick event. This is not part
293         // of the DOM specs, but is used for compatibility with the ondblclick="" attribute. This is treated
294         // as a separate event in other DOM-compliant browsers like Firefox, and so we do the same.
295         // FIXME: Is it okay that mouseEvent may have been mutated by scripts via initMouseEvent in dispatchEvent above?
296         Ref<MouseEvent> doubleClickEvent = MouseEvent::create(eventNames().dblclickEvent,
297             mouseEvent->bubbles() ? Event::CanBubble::Yes : Event::CanBubble::No,
298             mouseEvent->cancelable() ? Event::IsCancelable::Yes : Event::IsCancelable::No,
299             Event::IsComposed::Yes,
300             mouseEvent->view(), mouseEvent->detail(),
301             mouseEvent->screenX(), mouseEvent->screenY(), mouseEvent->clientX(), mouseEvent->clientY(),
302             mouseEvent->modifierKeys(), mouseEvent->button(), mouseEvent->buttons(), mouseEvent->syntheticClickType(), relatedTarget);
303
304         if (mouseEvent->defaultHandled())
305             doubleClickEvent->setDefaultHandled();
306
307         dispatchEvent(doubleClickEvent);
308         if (doubleClickEvent->defaultHandled() || doubleClickEvent->defaultPrevented())
309             return false;
310     }
311     return didNotSwallowEvent;
312 }
313
314 bool Element::dispatchWheelEvent(const PlatformWheelEvent& platformEvent)
315 {
316     auto event = WheelEvent::create(platformEvent, document().windowProxy());
317
318     // Events with no deltas are important because they convey platform information about scroll gestures
319     // and momentum beginning or ending. However, those events should not be sent to the DOM since some
320     // websites will break. They need to be dispatched because dispatching them will call into the default
321     // event handler, and our platform code will correctly handle the phase changes. Calling stopPropogation()
322     // will prevent the event from being sent to the DOM, but will still call the default event handler.
323     // FIXME: Move this logic into WheelEvent::create.
324     if (!platformEvent.deltaX() && !platformEvent.deltaY())
325         event->stopPropagation();
326
327     dispatchEvent(event);
328     return !event->defaultPrevented() && !event->defaultHandled();
329 }
330
331 bool Element::dispatchKeyEvent(const PlatformKeyboardEvent& platformEvent)
332 {
333     auto event = KeyboardEvent::create(platformEvent, document().windowProxy());
334
335     if (Frame* frame = document().frame()) {
336         if (frame->eventHandler().accessibilityPreventsEventPropagation(event))
337             event->stopPropagation();
338     }
339
340     dispatchEvent(event);
341     return !event->defaultPrevented() && !event->defaultHandled();
342 }
343
344 void Element::dispatchSimulatedClick(Event* underlyingEvent, SimulatedClickMouseEventOptions eventOptions, SimulatedClickVisualOptions visualOptions)
345 {
346     simulateClick(*this, underlyingEvent, eventOptions, visualOptions, SimulatedClickSource::UserAgent);
347 }
348
349 Ref<Node> Element::cloneNodeInternal(Document& targetDocument, CloningOperation type)
350 {
351     switch (type) {
352     case CloningOperation::OnlySelf:
353     case CloningOperation::SelfWithTemplateContent:
354         return cloneElementWithoutChildren(targetDocument);
355     case CloningOperation::Everything:
356         break;
357     }
358     return cloneElementWithChildren(targetDocument);
359 }
360
361 Ref<Element> Element::cloneElementWithChildren(Document& targetDocument)
362 {
363     Ref<Element> clone = cloneElementWithoutChildren(targetDocument);
364     cloneChildNodes(clone);
365     return clone;
366 }
367
368 Ref<Element> Element::cloneElementWithoutChildren(Document& targetDocument)
369 {
370     Ref<Element> clone = cloneElementWithoutAttributesAndChildren(targetDocument);
371
372     // This will catch HTML elements in the wrong namespace that are not correctly copied.
373     // This is a sanity check as HTML overloads some of the DOM methods.
374     ASSERT(isHTMLElement() == clone->isHTMLElement());
375
376     clone->cloneDataFromElement(*this);
377     return clone;
378 }
379
380 Ref<Element> Element::cloneElementWithoutAttributesAndChildren(Document& targetDocument)
381 {
382     return targetDocument.createElement(tagQName(), false);
383 }
384
385 Ref<Attr> Element::detachAttribute(unsigned index)
386 {
387     ASSERT(elementData());
388
389     const Attribute& attribute = elementData()->attributeAt(index);
390
391     RefPtr<Attr> attrNode = attrIfExists(attribute.name());
392     if (attrNode)
393         detachAttrNodeFromElementWithValue(attrNode.get(), attribute.value());
394     else
395         attrNode = Attr::create(document(), attribute.name(), attribute.value());
396
397     removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute);
398     return attrNode.releaseNonNull();
399 }
400
401 bool Element::removeAttribute(const QualifiedName& name)
402 {
403     if (!elementData())
404         return false;
405
406     unsigned index = elementData()->findAttributeIndexByName(name);
407     if (index == ElementData::attributeNotFound)
408         return false;
409
410     removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute);
411     return true;
412 }
413
414 void Element::setBooleanAttribute(const QualifiedName& name, bool value)
415 {
416     if (value)
417         setAttribute(name, emptyAtom());
418     else
419         removeAttribute(name);
420 }
421
422 NamedNodeMap& Element::attributes() const
423 {
424     ElementRareData& rareData = const_cast<Element*>(this)->ensureElementRareData();
425     if (NamedNodeMap* attributeMap = rareData.attributeMap())
426         return *attributeMap;
427
428     rareData.setAttributeMap(std::make_unique<NamedNodeMap>(const_cast<Element&>(*this)));
429     return *rareData.attributeMap();
430 }
431
432 Node::NodeType Element::nodeType() const
433 {
434     return ELEMENT_NODE;
435 }
436
437 bool Element::hasAttribute(const QualifiedName& name) const
438 {
439     return hasAttributeNS(name.namespaceURI(), name.localName());
440 }
441
442 void Element::synchronizeAllAttributes() const
443 {
444     if (!elementData())
445         return;
446     if (elementData()->styleAttributeIsDirty()) {
447         ASSERT(isStyledElement());
448         static_cast<const StyledElement*>(this)->synchronizeStyleAttributeInternal();
449     }
450
451     if (elementData()->animatedSVGAttributesAreDirty()) {
452         ASSERT(isSVGElement());
453         downcast<SVGElement>(*this).synchronizeAnimatedSVGAttribute(anyQName());
454     }
455 }
456
457 ALWAYS_INLINE void Element::synchronizeAttribute(const QualifiedName& name) const
458 {
459     if (!elementData())
460         return;
461     if (UNLIKELY(name == styleAttr && elementData()->styleAttributeIsDirty())) {
462         ASSERT_WITH_SECURITY_IMPLICATION(isStyledElement());
463         static_cast<const StyledElement*>(this)->synchronizeStyleAttributeInternal();
464         return;
465     }
466
467     if (UNLIKELY(elementData()->animatedSVGAttributesAreDirty())) {
468         ASSERT(isSVGElement());
469         downcast<SVGElement>(*this).synchronizeAnimatedSVGAttribute(name);
470     }
471 }
472
473 static ALWAYS_INLINE bool isStyleAttribute(const Element& element, const AtomicString& attributeLocalName)
474 {
475     if (shouldIgnoreAttributeCase(element))
476         return equalLettersIgnoringASCIICase(attributeLocalName, "style");
477     return attributeLocalName == styleAttr->localName();
478 }
479
480 ALWAYS_INLINE void Element::synchronizeAttribute(const AtomicString& localName) const
481 {
482     // This version of synchronizeAttribute() is streamlined for the case where you don't have a full QualifiedName,
483     // e.g when called from DOM API.
484     if (!elementData())
485         return;
486     if (elementData()->styleAttributeIsDirty() && isStyleAttribute(*this, localName)) {
487         ASSERT_WITH_SECURITY_IMPLICATION(isStyledElement());
488         static_cast<const StyledElement*>(this)->synchronizeStyleAttributeInternal();
489         return;
490     }
491     if (elementData()->animatedSVGAttributesAreDirty()) {
492         // We're not passing a namespace argument on purpose. SVGNames::*Attr are defined w/o namespaces as well.
493         ASSERT_WITH_SECURITY_IMPLICATION(isSVGElement());
494         downcast<SVGElement>(*this).synchronizeAnimatedSVGAttribute(QualifiedName(nullAtom(), localName, nullAtom()));
495     }
496 }
497
498 const AtomicString& Element::getAttribute(const QualifiedName& name) const
499 {
500     if (!elementData())
501         return nullAtom();
502     synchronizeAttribute(name);
503     if (const Attribute* attribute = findAttributeByName(name))
504         return attribute->value();
505     return nullAtom();
506 }
507
508 Vector<String> Element::getAttributeNames() const
509 {
510     Vector<String> attributesVector;
511     if (!hasAttributes())
512         return attributesVector;
513
514     auto attributes = attributesIterator();
515     attributesVector.reserveInitialCapacity(attributes.attributeCount());
516     for (auto& attribute : attributes)
517         attributesVector.uncheckedAppend(attribute.name().toString());
518     return attributesVector;
519 }
520
521 bool Element::isFocusable() const
522 {
523     if (!isConnected() || !supportsFocus())
524         return false;
525
526     if (!renderer()) {
527         // If the node is in a display:none tree it might say it needs style recalc but
528         // the whole document is actually up to date.
529         ASSERT(!needsStyleRecalc() || !document().childNeedsStyleRecalc());
530
531         // Elements in canvas fallback content are not rendered, but they are allowed to be
532         // focusable as long as their canvas is displayed and visible.
533         if (auto* canvas = ancestorsOfType<HTMLCanvasElement>(*this).first())
534             return canvas->renderer() && canvas->renderer()->style().visibility() == Visibility::Visible;
535     }
536
537     // FIXME: Even if we are not visible, we might have a child that is visible.
538     // Hyatt wants to fix that some day with a "has visible content" flag or the like.
539     if (!renderer() || renderer()->style().visibility() != Visibility::Visible)
540         return false;
541
542     return true;
543 }
544
545 bool Element::isUserActionElementInActiveChain() const
546 {
547     ASSERT(isUserActionElement());
548     return document().userActionElements().inActiveChain(*this);
549 }
550
551 bool Element::isUserActionElementActive() const
552 {
553     ASSERT(isUserActionElement());
554     return document().userActionElements().isActive(*this);
555 }
556
557 bool Element::isUserActionElementFocused() const
558 {
559     ASSERT(isUserActionElement());
560     return document().userActionElements().isFocused(*this);
561 }
562
563 bool Element::isUserActionElementHovered() const
564 {
565     ASSERT(isUserActionElement());
566     return document().userActionElements().isHovered(*this);
567 }
568
569 void Element::setActive(bool flag, bool pause)
570 {
571     if (flag == active())
572         return;
573
574     document().userActionElements().setActive(*this, flag);
575
576     auto* renderStyle = renderOrDisplayContentsStyle();
577     bool reactsToPress = (renderStyle && renderStyle->affectedByActive()) || styleAffectedByActive();
578     if (reactsToPress)
579         invalidateStyleForSubtree();
580
581     if (!renderer())
582         return;
583
584     if (renderer()->style().hasAppearance() && renderer()->theme().stateChanged(*renderer(), ControlStates::PressedState))
585         reactsToPress = true;
586
587     // The rest of this function implements a feature that only works if the
588     // platform supports immediate invalidations on the ChromeClient, so bail if
589     // that isn't supported.
590     if (!document().page()->chrome().client().supportsImmediateInvalidation())
591         return;
592
593     if (reactsToPress && pause) {
594         // The delay here is subtle. It relies on an assumption, namely that the amount of time it takes
595         // to repaint the "down" state of the control is about the same time as it would take to repaint the
596         // "up" state. Once you assume this, you can just delay for 100ms - that time (assuming that after you
597         // leave this method, it will be about that long before the flush of the up state happens again).
598 #ifdef HAVE_FUNC_USLEEP
599         MonotonicTime startTime = MonotonicTime::now();
600 #endif
601
602         document().updateStyleIfNeeded();
603
604         // Do an immediate repaint.
605         if (renderer())
606             renderer()->repaint();
607
608         // FIXME: Come up with a less ridiculous way of doing this.
609 #ifdef HAVE_FUNC_USLEEP
610         // Now pause for a small amount of time (1/10th of a second from before we repainted in the pressed state)
611         Seconds remainingTime = 100_ms - (MonotonicTime::now() - startTime);
612         if (remainingTime > 0_s)
613             usleep(static_cast<useconds_t>(remainingTime.microseconds()));
614 #endif
615     }
616 }
617
618 void Element::setFocus(bool flag)
619 {
620     if (flag == focused())
621         return;
622
623     document().userActionElements().setFocused(*this, flag);
624     invalidateStyleForSubtree();
625
626     for (Element* element = this; element; element = element->parentElementInComposedTree())
627         element->setHasFocusWithin(flag);
628 }
629
630 void Element::setHovered(bool flag)
631 {
632     if (flag == hovered())
633         return;
634
635     document().userActionElements().setHovered(*this, flag);
636
637     auto* style = renderOrDisplayContentsStyle();
638     if (style && (style->affectedByHover() || childrenAffectedByHover()))
639         invalidateStyleForSubtree();
640
641     if (!renderer()) {
642         // When setting hover to false, the style needs to be recalc'd even when
643         // there's no renderer (imagine setting display:none in the :hover class,
644         // if a nil renderer would prevent this element from recalculating its
645         // style, it would never go back to its normal style and remain
646         // stuck in its hovered style).
647         if (!flag && !style)
648             invalidateStyleForSubtree();
649
650         return;
651     }
652
653     if (style->hasAppearance())
654         renderer()->theme().stateChanged(*renderer(), ControlStates::HoverState);
655 }
656
657 // FIXME(webkit.org/b/161611): Take into account orientation/direction.
658 inline ScrollAlignment toScrollAlignment(Optional<ScrollLogicalPosition> position, bool isVertical)
659 {
660     switch (position.valueOr(isVertical ? ScrollLogicalPosition::Start : ScrollLogicalPosition::Nearest)) {
661     case ScrollLogicalPosition::Start:
662         return isVertical ? ScrollAlignment::alignTopAlways : ScrollAlignment::alignLeftAlways;
663     case ScrollLogicalPosition::Center:
664         return ScrollAlignment::alignCenterAlways;
665     case ScrollLogicalPosition::End:
666         return isVertical ? ScrollAlignment::alignBottomAlways : ScrollAlignment::alignRightAlways;
667     case ScrollLogicalPosition::Nearest:
668         return ScrollAlignment::alignToEdgeIfNeeded;
669     default:
670         ASSERT_NOT_REACHED();
671         return ScrollAlignment::alignToEdgeIfNeeded;
672     }
673 }
674
675 void Element::scrollIntoView(Optional<Variant<bool, ScrollIntoViewOptions>>&& arg)
676 {
677     document().updateLayoutIgnorePendingStylesheets();
678
679     if (!renderer())
680         return;
681
682     bool insideFixed;
683     LayoutRect absoluteBounds = renderer()->absoluteAnchorRect(&insideFixed);
684
685     // FIXME(webkit.org/b/188043): Support ScrollBehavior.
686     ScrollIntoViewOptions options;
687     if (arg) {
688         auto value = arg.value();
689         if (WTF::holds_alternative<ScrollIntoViewOptions>(value))
690             options = WTF::get<ScrollIntoViewOptions>(value);
691         else if (!WTF::get<bool>(value))
692             options.blockPosition = ScrollLogicalPosition::End;
693     }
694
695     ScrollAlignment alignX = toScrollAlignment(options.inlinePosition, false);
696     ScrollAlignment alignY = toScrollAlignment(options.blockPosition, true);
697     renderer()->scrollRectToVisible(absoluteBounds, insideFixed, { SelectionRevealMode::Reveal, alignX, alignY, ShouldAllowCrossOriginScrolling::No });
698 }
699
700 void Element::scrollIntoView(bool alignToTop) 
701 {
702     document().updateLayoutIgnorePendingStylesheets();
703
704     if (!renderer())
705         return;
706
707     bool insideFixed;
708     LayoutRect absoluteBounds = renderer()->absoluteAnchorRect(&insideFixed);
709     // Align to the top / bottom and to the closest edge.
710     if (alignToTop)
711         renderer()->scrollRectToVisible(absoluteBounds, insideFixed, { SelectionRevealMode::Reveal, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways, ShouldAllowCrossOriginScrolling::No });
712     else
713         renderer()->scrollRectToVisible(absoluteBounds, insideFixed, { SelectionRevealMode::Reveal, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignBottomAlways, ShouldAllowCrossOriginScrolling::No });
714 }
715
716 void Element::scrollIntoViewIfNeeded(bool centerIfNeeded)
717 {
718     document().updateLayoutIgnorePendingStylesheets();
719
720     if (!renderer())
721         return;
722
723     bool insideFixed;
724     LayoutRect absoluteBounds = renderer()->absoluteAnchorRect(&insideFixed);
725     if (centerIfNeeded)
726         renderer()->scrollRectToVisible(absoluteBounds, insideFixed, { SelectionRevealMode::Reveal, ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeeded, ShouldAllowCrossOriginScrolling::No });
727     else
728         renderer()->scrollRectToVisible(absoluteBounds, insideFixed, { SelectionRevealMode::Reveal, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded, ShouldAllowCrossOriginScrolling::No });
729 }
730
731 void Element::scrollIntoViewIfNotVisible(bool centerIfNotVisible)
732 {
733     document().updateLayoutIgnorePendingStylesheets();
734     
735     if (!renderer())
736         return;
737     
738     bool insideFixed;
739     LayoutRect absoluteBounds = renderer()->absoluteAnchorRect(&insideFixed);
740     if (centerIfNotVisible)
741         renderer()->scrollRectToVisible(absoluteBounds, insideFixed, { SelectionRevealMode::Reveal, ScrollAlignment::alignCenterIfNotVisible, ScrollAlignment::alignCenterIfNotVisible, ShouldAllowCrossOriginScrolling::No });
742     else
743         renderer()->scrollRectToVisible(absoluteBounds, insideFixed, { SelectionRevealMode::Reveal, ScrollAlignment::alignToEdgeIfNotVisible, ScrollAlignment::alignToEdgeIfNotVisible, ShouldAllowCrossOriginScrolling::No });
744 }
745
746 void Element::scrollBy(const ScrollToOptions& options)
747 {
748     ScrollToOptions scrollToOptions = normalizeNonFiniteCoordinatesOrFallBackTo(options, 0, 0);
749     scrollToOptions.left.value() += scrollLeft();
750     scrollToOptions.top.value() += scrollTop();
751     scrollTo(scrollToOptions);
752 }
753
754 void Element::scrollBy(double x, double y)
755 {
756     scrollBy({ x, y });
757 }
758
759 void Element::scrollTo(const ScrollToOptions& options, ScrollClamping clamping)
760 {
761     if (!document().settings().CSSOMViewScrollingAPIEnabled()) {
762         // If the element is the root element and document is in quirks mode, terminate these steps.
763         // Note that WebKit always uses quirks mode document scrolling behavior. See Document::scrollingElement().
764         if (this == document().documentElement())
765             return;
766     }
767
768     document().updateLayoutIgnorePendingStylesheets();
769
770     if (document().scrollingElement() == this) {
771         // If the element is the scrolling element and is not potentially scrollable,
772         // invoke scroll() on window with options as the only argument, and terminate these steps.
773         // FIXME: Scrolling an independently scrollable body is broken: webkit.org/b/161612.
774         auto window = makeRefPtr(document().domWindow());
775         if (!window)
776             return;
777
778         window->scrollTo(options);
779         return;
780     }
781
782     // If the element does not have any associated CSS layout box, the element has no associated scrolling box,
783     // or the element has no overflow, terminate these steps.
784     RenderBox* renderer = renderBox();
785     if (!renderer || !renderer->hasOverflowClip())
786         return;
787
788     ScrollToOptions scrollToOptions = normalizeNonFiniteCoordinatesOrFallBackTo(options,
789         adjustForAbsoluteZoom(renderer->scrollLeft(), *renderer),
790         adjustForAbsoluteZoom(renderer->scrollTop(), *renderer)
791     );
792     renderer->setScrollLeft(clampToInteger(scrollToOptions.left.value() * renderer->style().effectiveZoom()), clamping);
793     renderer->setScrollTop(clampToInteger(scrollToOptions.top.value() * renderer->style().effectiveZoom()), clamping);
794 }
795
796 void Element::scrollTo(double x, double y)
797 {
798     scrollTo({ x, y });
799 }
800
801 void Element::scrollByUnits(int units, ScrollGranularity granularity)
802 {
803     document().updateLayoutIgnorePendingStylesheets();
804
805     auto* renderer = this->renderer();
806     if (!renderer)
807         return;
808
809     if (!renderer->hasOverflowClip())
810         return;
811
812     ScrollDirection direction = ScrollDown;
813     if (units < 0) {
814         direction = ScrollUp;
815         units = -units;
816     }
817     Element* stopElement = this;
818     downcast<RenderBox>(*renderer).scroll(direction, granularity, units, &stopElement);
819 }
820
821 void Element::scrollByLines(int lines)
822 {
823     scrollByUnits(lines, ScrollByLine);
824 }
825
826 void Element::scrollByPages(int pages)
827 {
828     scrollByUnits(pages, ScrollByPage);
829 }
830
831 static double localZoomForRenderer(const RenderElement& renderer)
832 {
833     // FIXME: This does the wrong thing if two opposing zooms are in effect and canceled each
834     // other out, but the alternative is that we'd have to crawl up the whole render tree every
835     // time (or store an additional bit in the RenderStyle to indicate that a zoom was specified).
836     double zoomFactor = 1;
837     if (renderer.style().effectiveZoom() != 1) {
838         // Need to find the nearest enclosing RenderElement that set up
839         // a differing zoom, and then we divide our result by it to eliminate the zoom.
840         const RenderElement* prev = &renderer;
841         for (RenderElement* curr = prev->parent(); curr; curr = curr->parent()) {
842             if (curr->style().effectiveZoom() != prev->style().effectiveZoom()) {
843                 zoomFactor = prev->style().zoom();
844                 break;
845             }
846             prev = curr;
847         }
848         if (prev->isRenderView())
849             zoomFactor = prev->style().zoom();
850     }
851     return zoomFactor;
852 }
853
854 static double adjustForLocalZoom(LayoutUnit value, const RenderElement& renderer, double& zoomFactor)
855 {
856     zoomFactor = localZoomForRenderer(renderer);
857     if (zoomFactor == 1)
858         return value.toDouble();
859     return value.toDouble() / zoomFactor;
860 }
861
862 static int adjustContentsScrollPositionOrSizeForZoom(int value, const Frame& frame)
863 {
864     double zoomFactor = frame.pageZoomFactor() * frame.frameScaleFactor();
865     if (zoomFactor == 1)
866         return value;
867     // FIXME (webkit.org/b/189397): Why can't we just ceil/floor?
868     // Needed because of truncation (rather than rounding) when scaling up.
869     if (zoomFactor > 1)
870         value++;
871     return static_cast<int>(value / zoomFactor);
872 }
873
874 enum LegacyCSSOMElementMetricsRoundingStrategy { Round, Floor };
875
876 static bool subpixelMetricsEnabled(const Document& document)
877 {
878     return document.settings().subpixelCSSOMElementMetricsEnabled();
879 }
880
881 static double convertToNonSubpixelValueIfNeeded(double value, const Document& document, LegacyCSSOMElementMetricsRoundingStrategy roundStrategy = Round)
882 {
883     return subpixelMetricsEnabled(document) ? value : roundStrategy == Round ? round(value) : floor(value);
884 }
885
886 static double adjustOffsetForZoomAndSubpixelLayout(RenderBoxModelObject* renderer, const LayoutUnit& offset)
887 {
888     LayoutUnit offsetLeft = subpixelMetricsEnabled(renderer->document()) ? offset : LayoutUnit(roundToInt(offset));
889     double zoomFactor = 1;
890     double offsetLeftAdjustedWithZoom = adjustForLocalZoom(offsetLeft, *renderer, zoomFactor);
891     return convertToNonSubpixelValueIfNeeded(offsetLeftAdjustedWithZoom, renderer->document(), zoomFactor == 1 ? Floor : Round);
892 }
893
894 static HashSet<TreeScope*> collectAncestorTreeScopeAsHashSet(Node& node)
895 {
896     HashSet<TreeScope*> ancestors;
897     for (auto* currentScope = &node.treeScope(); currentScope; currentScope = currentScope->parentTreeScope())
898         ancestors.add(currentScope);
899     return ancestors;
900 }
901
902 double Element::offsetLeftForBindings()
903 {
904     auto offset = offsetLeft();
905
906     auto parent = makeRefPtr(offsetParent());
907     if (!parent || !parent->isInShadowTree())
908         return offset;
909
910     ASSERT(&parent->document() == &document());
911     if (&parent->treeScope() == &treeScope())
912         return offset;
913
914     auto ancestorTreeScopes = collectAncestorTreeScopeAsHashSet(*this);
915     while (parent && !ancestorTreeScopes.contains(&parent->treeScope())) {
916         offset += parent->offsetLeft();
917         parent = parent->offsetParent();
918     }
919
920     return offset;
921 }
922
923 double Element::offsetLeft()
924 {
925     document().updateLayoutIgnorePendingStylesheets();
926     if (RenderBoxModelObject* renderer = renderBoxModelObject())
927         return adjustOffsetForZoomAndSubpixelLayout(renderer, renderer->offsetLeft());
928     return 0;
929 }
930
931 double Element::offsetTopForBindings()
932 {
933     auto offset = offsetTop();
934
935     auto parent = makeRefPtr(offsetParent());
936     if (!parent || !parent->isInShadowTree())
937         return offset;
938
939     ASSERT(&parent->document() == &document());
940     if (&parent->treeScope() == &treeScope())
941         return offset;
942
943     auto ancestorTreeScopes = collectAncestorTreeScopeAsHashSet(*this);
944     while (parent && !ancestorTreeScopes.contains(&parent->treeScope())) {
945         offset += parent->offsetTop();
946         parent = parent->offsetParent();
947     }
948
949     return offset;
950 }
951
952 double Element::offsetTop()
953 {
954     document().updateLayoutIgnorePendingStylesheets();
955     if (RenderBoxModelObject* renderer = renderBoxModelObject())
956         return adjustOffsetForZoomAndSubpixelLayout(renderer, renderer->offsetTop());
957     return 0;
958 }
959
960 double Element::offsetWidth()
961 {
962     document().updateLayoutIfDimensionsOutOfDate(*this, WidthDimensionsCheck);
963     if (RenderBoxModelObject* renderer = renderBoxModelObject()) {
964         LayoutUnit offsetWidth = subpixelMetricsEnabled(renderer->document()) ? renderer->offsetWidth() : LayoutUnit(roundToInt(renderer->offsetWidth()));
965         return convertToNonSubpixelValueIfNeeded(adjustLayoutUnitForAbsoluteZoom(offsetWidth, *renderer).toDouble(), renderer->document());
966     }
967     return 0;
968 }
969
970 double Element::offsetHeight()
971 {
972     document().updateLayoutIfDimensionsOutOfDate(*this, HeightDimensionsCheck);
973     if (RenderBoxModelObject* renderer = renderBoxModelObject()) {
974         LayoutUnit offsetHeight = subpixelMetricsEnabled(renderer->document()) ? renderer->offsetHeight() : LayoutUnit(roundToInt(renderer->offsetHeight()));
975         return convertToNonSubpixelValueIfNeeded(adjustLayoutUnitForAbsoluteZoom(offsetHeight, *renderer).toDouble(), renderer->document());
976     }
977     return 0;
978 }
979
980 Element* Element::offsetParentForBindings()
981 {
982     Element* element = offsetParent();
983     if (!element || !element->isInShadowTree())
984         return element;
985     while (element && !isDescendantOrShadowDescendantOf(&element->rootNode()))
986         element = element->offsetParent();
987     return element;
988 }
989
990 Element* Element::offsetParent()
991 {
992     document().updateLayoutIgnorePendingStylesheets();
993     auto renderer = this->renderer();
994     if (!renderer)
995         return nullptr;
996     auto offsetParent = renderer->offsetParent();
997     if (!offsetParent)
998         return nullptr;
999     return offsetParent->element();
1000 }
1001
1002 double Element::clientLeft()
1003 {
1004     document().updateLayoutIgnorePendingStylesheets();
1005
1006     if (auto* renderer = renderBox()) {
1007         LayoutUnit clientLeft = subpixelMetricsEnabled(renderer->document()) ? renderer->clientLeft() : LayoutUnit(roundToInt(renderer->clientLeft()));
1008         return convertToNonSubpixelValueIfNeeded(adjustLayoutUnitForAbsoluteZoom(clientLeft, *renderer).toDouble(), renderer->document());
1009     }
1010     return 0;
1011 }
1012
1013 double Element::clientTop()
1014 {
1015     document().updateLayoutIgnorePendingStylesheets();
1016
1017     if (auto* renderer = renderBox()) {
1018         LayoutUnit clientTop = subpixelMetricsEnabled(renderer->document()) ? renderer->clientTop() : LayoutUnit(roundToInt(renderer->clientTop()));
1019         return convertToNonSubpixelValueIfNeeded(adjustLayoutUnitForAbsoluteZoom(clientTop, *renderer).toDouble(), renderer->document());
1020     }
1021     return 0;
1022 }
1023
1024 double Element::clientWidth()
1025 {
1026     document().updateLayoutIfDimensionsOutOfDate(*this, WidthDimensionsCheck);
1027
1028     if (!document().hasLivingRenderTree())
1029         return 0;
1030
1031     RenderView& renderView = *document().renderView();
1032
1033     // When in strict mode, clientWidth for the document element should return the width of the containing frame.
1034     // When in quirks mode, clientWidth for the body element should return the width of the containing frame.
1035     bool inQuirksMode = document().inQuirksMode();
1036     if ((!inQuirksMode && document().documentElement() == this) || (inQuirksMode && isHTMLElement() && document().bodyOrFrameset() == this))
1037         return adjustForAbsoluteZoom(renderView.frameView().layoutWidth(), renderView);
1038     
1039     if (RenderBox* renderer = renderBox()) {
1040         LayoutUnit clientWidth = subpixelMetricsEnabled(renderer->document()) ? renderer->clientWidth() : LayoutUnit(roundToInt(renderer->clientWidth()));
1041         return convertToNonSubpixelValueIfNeeded(adjustLayoutUnitForAbsoluteZoom(clientWidth, *renderer).toDouble(), renderer->document());
1042     }
1043     return 0;
1044 }
1045
1046 double Element::clientHeight()
1047 {
1048     document().updateLayoutIfDimensionsOutOfDate(*this, HeightDimensionsCheck);
1049     if (!document().hasLivingRenderTree())
1050         return 0;
1051
1052     RenderView& renderView = *document().renderView();
1053
1054     // When in strict mode, clientHeight for the document element should return the height of the containing frame.
1055     // When in quirks mode, clientHeight for the body element should return the height of the containing frame.
1056     bool inQuirksMode = document().inQuirksMode();
1057     if ((!inQuirksMode && document().documentElement() == this) || (inQuirksMode && isHTMLElement() && document().bodyOrFrameset() == this))
1058         return adjustForAbsoluteZoom(renderView.frameView().layoutHeight(), renderView);
1059
1060     if (RenderBox* renderer = renderBox()) {
1061         LayoutUnit clientHeight = subpixelMetricsEnabled(renderer->document()) ? renderer->clientHeight() : LayoutUnit(roundToInt(renderer->clientHeight()));
1062         return convertToNonSubpixelValueIfNeeded(adjustLayoutUnitForAbsoluteZoom(clientHeight, *renderer).toDouble(), renderer->document());
1063     }
1064     return 0;
1065 }
1066
1067 ALWAYS_INLINE Frame* Element::documentFrameWithNonNullView() const
1068 {
1069     auto* frame = document().frame();
1070     return frame && frame->view() ? frame : nullptr;
1071 }
1072
1073 int Element::scrollLeft()
1074 {
1075     document().updateLayoutIgnorePendingStylesheets();
1076
1077     if (document().scrollingElement() == this) {
1078         if (auto* frame = documentFrameWithNonNullView())
1079             return adjustContentsScrollPositionOrSizeForZoom(frame->view()->contentsScrollPosition().x(), *frame);
1080         return 0;
1081     }
1082
1083     if (auto* renderer = renderBox())
1084         return adjustForAbsoluteZoom(renderer->scrollLeft(), *renderer);
1085     return 0;
1086 }
1087
1088 int Element::scrollTop()
1089 {
1090     document().updateLayoutIgnorePendingStylesheets();
1091
1092     if (document().scrollingElement() == this) {
1093         if (auto* frame = documentFrameWithNonNullView())
1094             return adjustContentsScrollPositionOrSizeForZoom(frame->view()->contentsScrollPosition().y(), *frame);
1095         return 0;
1096     }
1097
1098     if (RenderBox* renderer = renderBox())
1099         return adjustForAbsoluteZoom(renderer->scrollTop(), *renderer);
1100     return 0;
1101 }
1102
1103 void Element::setScrollLeft(int newLeft)
1104 {
1105     document().updateLayoutIgnorePendingStylesheets();
1106
1107     if (document().scrollingElement() == this) {
1108         if (auto* frame = documentFrameWithNonNullView())
1109             frame->view()->setScrollPosition(IntPoint(static_cast<int>(newLeft * frame->pageZoomFactor() * frame->frameScaleFactor()), frame->view()->scrollY()));
1110         return;
1111     }
1112
1113     if (auto* renderer = renderBox()) {
1114         renderer->setScrollLeft(static_cast<int>(newLeft * renderer->style().effectiveZoom()));
1115         if (auto* scrollableArea = renderer->layer())
1116             scrollableArea->setScrolledProgrammatically(true);
1117     }
1118 }
1119
1120 void Element::setScrollTop(int newTop)
1121 {
1122     document().updateLayoutIgnorePendingStylesheets();
1123
1124     if (document().scrollingElement() == this) {
1125         if (auto* frame = documentFrameWithNonNullView())
1126             frame->view()->setScrollPosition(IntPoint(frame->view()->scrollX(), static_cast<int>(newTop * frame->pageZoomFactor() * frame->frameScaleFactor())));
1127         return;
1128     }
1129
1130     if (auto* renderer = renderBox()) {
1131         renderer->setScrollTop(static_cast<int>(newTop * renderer->style().effectiveZoom()));
1132         if (auto* scrollableArea = renderer->layer())
1133             scrollableArea->setScrolledProgrammatically(true);
1134     }
1135 }
1136
1137 int Element::scrollWidth()
1138 {
1139     document().updateLayoutIfDimensionsOutOfDate(*this, WidthDimensionsCheck);
1140
1141     if (document().scrollingElement() == this) {
1142         // FIXME (webkit.org/b/182289): updateLayoutIfDimensionsOutOfDate seems to ignore zoom level change.
1143         document().updateLayoutIgnorePendingStylesheets();
1144         if (auto* frame = documentFrameWithNonNullView())
1145             return adjustContentsScrollPositionOrSizeForZoom(frame->view()->contentsWidth(), *frame);
1146         return 0;
1147     }
1148
1149     if (auto* renderer = renderBox())
1150         return adjustForAbsoluteZoom(renderer->scrollWidth(), *renderer);
1151     return 0;
1152 }
1153
1154 int Element::scrollHeight()
1155 {
1156     document().updateLayoutIfDimensionsOutOfDate(*this, HeightDimensionsCheck);
1157
1158     if (document().scrollingElement() == this) {
1159         // FIXME (webkit.org/b/182289): updateLayoutIfDimensionsOutOfDate seems to ignore zoom level change.
1160         document().updateLayoutIgnorePendingStylesheets();
1161         if (auto* frame = documentFrameWithNonNullView())
1162             return adjustContentsScrollPositionOrSizeForZoom(frame->view()->contentsHeight(), *frame);
1163         return 0;
1164     }
1165
1166     if (auto* renderer = renderBox())
1167         return adjustForAbsoluteZoom(renderer->scrollHeight(), *renderer);
1168     return 0;
1169 }
1170
1171 IntRect Element::boundsInRootViewSpace()
1172 {
1173     document().updateLayoutIgnorePendingStylesheets();
1174
1175     FrameView* view = document().view();
1176     if (!view)
1177         return IntRect();
1178
1179     Vector<FloatQuad> quads;
1180
1181     if (isSVGElement() && renderer()) {
1182         // Get the bounding rectangle from the SVG model.
1183         SVGElement& svgElement = downcast<SVGElement>(*this);
1184         FloatRect localRect;
1185         if (svgElement.getBoundingBox(localRect))
1186             quads.append(renderer()->localToAbsoluteQuad(localRect));
1187     } else {
1188         // Get the bounding rectangle from the box model.
1189         if (renderBoxModelObject())
1190             renderBoxModelObject()->absoluteQuads(quads);
1191     }
1192
1193     if (quads.isEmpty())
1194         return IntRect();
1195
1196     IntRect result = quads[0].enclosingBoundingBox();
1197     for (size_t i = 1; i < quads.size(); ++i)
1198         result.unite(quads[i].enclosingBoundingBox());
1199
1200     result = view->contentsToRootView(result);
1201     return result;
1202 }
1203
1204 static bool layoutOverflowRectContainsAllDescendants(const RenderBox& renderBox)
1205 {
1206     if (renderBox.isRenderView())
1207         return true;
1208
1209     if (!renderBox.element())
1210         return false;
1211
1212     // If there are any position:fixed inside of us, game over.
1213     if (auto* viewPositionedObjects = renderBox.view().positionedObjects()) {
1214         for (auto* positionedBox : *viewPositionedObjects) {
1215             if (positionedBox == &renderBox)
1216                 continue;
1217             if (positionedBox->isFixedPositioned() && renderBox.element()->contains(positionedBox->element()))
1218                 return false;
1219         }
1220     }
1221
1222     if (renderBox.canContainAbsolutelyPositionedObjects()) {
1223         // Our layout overflow will include all descendant positioned elements.
1224         return true;
1225     }
1226
1227     // This renderer may have positioned descendants whose containing block is some ancestor.
1228     if (auto* containingBlock = renderBox.containingBlockForAbsolutePosition()) {
1229         if (auto* positionedObjects = containingBlock->positionedObjects()) {
1230             for (auto* positionedBox : *positionedObjects) {
1231                 if (positionedBox == &renderBox)
1232                     continue;
1233                 if (renderBox.element()->contains(positionedBox->element()))
1234                     return false;
1235             }
1236         }
1237     }
1238     return false;
1239 }
1240
1241 LayoutRect Element::absoluteEventBounds(bool& boundsIncludeAllDescendantElements, bool& includesFixedPositionElements)
1242 {
1243     boundsIncludeAllDescendantElements = false;
1244     includesFixedPositionElements = false;
1245
1246     if (!renderer())
1247         return LayoutRect();
1248
1249     LayoutRect result;
1250     if (isSVGElement()) {
1251         // Get the bounding rectangle from the SVG model.
1252         SVGElement& svgElement = downcast<SVGElement>(*this);
1253         FloatRect localRect;
1254         if (svgElement.getBoundingBox(localRect, SVGLocatable::DisallowStyleUpdate))
1255             result = LayoutRect(renderer()->localToAbsoluteQuad(localRect, UseTransforms, &includesFixedPositionElements).boundingBox());
1256     } else {
1257         auto* renderer = this->renderer();
1258         if (is<RenderBox>(renderer)) {
1259             auto& box = downcast<RenderBox>(*renderer);
1260
1261             bool computedBounds = false;
1262             
1263             if (RenderFragmentedFlow* fragmentedFlow = box.enclosingFragmentedFlow()) {
1264                 bool wasFixed = false;
1265                 Vector<FloatQuad> quads;
1266                 FloatRect localRect(0, 0, box.width(), box.height());
1267                 if (fragmentedFlow->absoluteQuadsForBox(quads, &wasFixed, &box, localRect.y(), localRect.maxY())) {
1268                     FloatRect quadBounds = quads[0].boundingBox();
1269                     for (size_t i = 1; i < quads.size(); ++i)
1270                         quadBounds.unite(quads[i].boundingBox());
1271                     
1272                     result = LayoutRect(quadBounds);
1273                     computedBounds = true;
1274                 } else {
1275                     // Probably columns. Just return the bounds of the multicol block for now.
1276                     // FIXME: this doesn't handle nested columns.
1277                     RenderElement* multicolContainer = fragmentedFlow->parent();
1278                     if (multicolContainer && is<RenderBox>(multicolContainer)) {
1279                         auto overflowRect = downcast<RenderBox>(*multicolContainer).layoutOverflowRect();
1280                         result = LayoutRect(multicolContainer->localToAbsoluteQuad(FloatRect(overflowRect), UseTransforms, &includesFixedPositionElements).boundingBox());
1281                         computedBounds = true;
1282                     }
1283                 }
1284             }
1285
1286             if (!computedBounds) {
1287                 LayoutRect overflowRect = box.layoutOverflowRect();
1288                 result = LayoutRect(box.localToAbsoluteQuad(FloatRect(overflowRect), UseTransforms, &includesFixedPositionElements).boundingBox());
1289                 boundsIncludeAllDescendantElements = layoutOverflowRectContainsAllDescendants(box);
1290             }
1291         } else
1292             result = LayoutRect(renderer->absoluteBoundingBoxRect(true /* useTransforms */, &includesFixedPositionElements));
1293     }
1294
1295     return result;
1296 }
1297
1298 LayoutRect Element::absoluteEventBoundsOfElementAndDescendants(bool& includesFixedPositionElements)
1299 {
1300     bool boundsIncludeDescendants;
1301     LayoutRect result = absoluteEventBounds(boundsIncludeDescendants, includesFixedPositionElements);
1302     if (boundsIncludeDescendants)
1303         return result;
1304
1305     for (auto& child : childrenOfType<Element>(*this)) {
1306         bool includesFixedPosition = false;
1307         LayoutRect childBounds = child.absoluteEventBoundsOfElementAndDescendants(includesFixedPosition);
1308         includesFixedPositionElements |= includesFixedPosition;
1309         result.unite(childBounds);
1310     }
1311
1312     return result;
1313 }
1314
1315 LayoutRect Element::absoluteEventHandlerBounds(bool& includesFixedPositionElements)
1316 {
1317     // This is not web-exposed, so don't call the FOUC-inducing updateLayoutIgnorePendingStylesheets().
1318     FrameView* frameView = document().view();
1319     if (!frameView)
1320         return LayoutRect();
1321
1322     return absoluteEventBoundsOfElementAndDescendants(includesFixedPositionElements);
1323 }
1324
1325 static Optional<std::pair<RenderObject*, LayoutRect>> listBoxElementBoundingBox(Element& element)
1326 {
1327     HTMLSelectElement* selectElement;
1328     bool isGroup;
1329     if (is<HTMLOptionElement>(element)) {
1330         selectElement = downcast<HTMLOptionElement>(element).ownerSelectElement();
1331         isGroup = false;
1332     } else if (is<HTMLOptGroupElement>(element)) {
1333         selectElement = downcast<HTMLOptGroupElement>(element).ownerSelectElement();
1334         isGroup = true;
1335     } else
1336         return WTF::nullopt;
1337
1338     if (!selectElement || !selectElement->renderer() || !is<RenderListBox>(selectElement->renderer()))
1339         return WTF::nullopt;
1340
1341     auto& renderer = downcast<RenderListBox>(*selectElement->renderer());
1342     Optional<LayoutRect> boundingBox;
1343     int optionIndex = 0;
1344     for (auto* item : selectElement->listItems()) {
1345         if (item == &element) {
1346             LayoutPoint additionOffset;
1347             boundingBox = renderer.itemBoundingBoxRect(additionOffset, optionIndex);
1348             if (!isGroup)
1349                 break;
1350         } else if (isGroup && boundingBox) {
1351             if (item->parentNode() != &element)
1352                 break;
1353             LayoutPoint additionOffset;
1354             boundingBox->setHeight(boundingBox->height() + renderer.itemBoundingBoxRect(additionOffset, optionIndex).height());
1355         }
1356         ++optionIndex;
1357     }
1358
1359     if (!boundingBox)
1360         return WTF::nullopt;
1361
1362     return std::pair<RenderObject*, LayoutRect> { &renderer, boundingBox.value() };
1363 }
1364
1365 Ref<DOMRectList> Element::getClientRects()
1366 {
1367     document().updateLayoutIgnorePendingStylesheets();
1368
1369     RenderObject* renderer = this->renderer();
1370     Vector<FloatQuad> quads;
1371
1372     if (auto pair = listBoxElementBoundingBox(*this)) {
1373         renderer = pair.value().first;
1374         quads.append(renderer->localToAbsoluteQuad(FloatQuad { pair.value().second }));
1375     } else if (auto* renderBoxModelObject = this->renderBoxModelObject())
1376         renderBoxModelObject->absoluteQuads(quads);
1377
1378     // FIXME: Handle SVG elements.
1379     // FIXME: Handle table/inline-table with a caption.
1380
1381     if (quads.isEmpty())
1382         return DOMRectList::create();
1383
1384     document().convertAbsoluteToClientQuads(quads, renderer->style());
1385     return DOMRectList::create(quads);
1386 }
1387
1388 FloatRect Element::boundingClientRect()
1389 {
1390     document().updateLayoutIgnorePendingStylesheets();
1391
1392     RenderObject* renderer = this->renderer();
1393     Vector<FloatQuad> quads;
1394     if (isSVGElement() && renderer && !renderer->isSVGRoot()) {
1395         // Get the bounding rectangle from the SVG model.
1396         SVGElement& svgElement = downcast<SVGElement>(*this);
1397         FloatRect localRect;
1398         if (svgElement.getBoundingBox(localRect))
1399             quads.append(renderer->localToAbsoluteQuad(localRect));
1400     } else if (auto pair = listBoxElementBoundingBox(*this)) {
1401         renderer = pair.value().first;
1402         quads.append(renderer->localToAbsoluteQuad(FloatQuad { pair.value().second }));
1403     } else if (auto* renderBoxModelObject = this->renderBoxModelObject())
1404         renderBoxModelObject->absoluteQuads(quads);
1405
1406     if (quads.isEmpty())
1407         return { };
1408
1409     FloatRect result = quads[0].boundingBox();
1410     for (size_t i = 1; i < quads.size(); ++i)
1411         result.unite(quads[i].boundingBox());
1412
1413     document().convertAbsoluteToClientRect(result, renderer->style());
1414     return result;
1415 }
1416
1417 Ref<DOMRect> Element::getBoundingClientRect()
1418 {
1419     return DOMRect::create(boundingClientRect());
1420 }
1421
1422 // Note that this is not web-exposed, and does not use the same coordinate system as getBoundingClientRect() and friends.
1423 IntRect Element::clientRect() const
1424 {
1425     if (RenderObject* renderer = this->renderer())
1426         return document().view()->contentsToRootView(renderer->absoluteBoundingBoxRect());
1427     return IntRect();
1428 }
1429     
1430 IntRect Element::screenRect() const
1431 {
1432     if (RenderObject* renderer = this->renderer())
1433         return document().view()->contentsToScreen(renderer->absoluteBoundingBoxRect());
1434     return IntRect();
1435 }
1436
1437 const AtomicString& Element::getAttribute(const AtomicString& qualifiedName) const
1438 {
1439     if (!elementData())
1440         return nullAtom();
1441     synchronizeAttribute(qualifiedName);
1442     if (const Attribute* attribute = elementData()->findAttributeByName(qualifiedName, shouldIgnoreAttributeCase(*this)))
1443         return attribute->value();
1444     return nullAtom();
1445 }
1446
1447 const AtomicString& Element::getAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const
1448 {
1449     return getAttribute(QualifiedName(nullAtom(), localName, namespaceURI));
1450 }
1451
1452 // https://dom.spec.whatwg.org/#dom-element-toggleattribute
1453 ExceptionOr<bool> Element::toggleAttribute(const AtomicString& qualifiedName, Optional<bool> force)
1454 {
1455     if (!Document::isValidName(qualifiedName))
1456         return Exception { InvalidCharacterError };
1457
1458     synchronizeAttribute(qualifiedName);
1459
1460     auto caseAdjustedQualifiedName = shouldIgnoreAttributeCase(*this) ? qualifiedName.convertToASCIILowercase() : qualifiedName;
1461     unsigned index = elementData() ? elementData()->findAttributeIndexByName(caseAdjustedQualifiedName, false) : ElementData::attributeNotFound;
1462     if (index == ElementData::attributeNotFound) {
1463         if (!force || *force) {
1464             setAttributeInternal(index, QualifiedName { nullAtom(), caseAdjustedQualifiedName, nullAtom() }, emptyString(), NotInSynchronizationOfLazyAttribute);
1465             return true;
1466         }
1467         return false;
1468     }
1469
1470     if (!force || !*force) {
1471         removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute);
1472         return false;
1473     }
1474     return true;
1475 }
1476
1477 ExceptionOr<void> Element::setAttribute(const AtomicString& qualifiedName, const AtomicString& value)
1478 {
1479     if (!Document::isValidName(qualifiedName))
1480         return Exception { InvalidCharacterError };
1481
1482     synchronizeAttribute(qualifiedName);
1483     auto caseAdjustedQualifiedName = shouldIgnoreAttributeCase(*this) ? qualifiedName.convertToASCIILowercase() : qualifiedName;
1484     unsigned index = elementData() ? elementData()->findAttributeIndexByName(caseAdjustedQualifiedName, false) : ElementData::attributeNotFound;
1485     auto name = index != ElementData::attributeNotFound ? attributeAt(index).name() : QualifiedName { nullAtom(), caseAdjustedQualifiedName, nullAtom() };
1486     setAttributeInternal(index, name, value, NotInSynchronizationOfLazyAttribute);
1487
1488     return { };
1489 }
1490
1491 void Element::setAttribute(const QualifiedName& name, const AtomicString& value)
1492 {
1493     synchronizeAttribute(name);
1494     unsigned index = elementData() ? elementData()->findAttributeIndexByName(name) : ElementData::attributeNotFound;
1495     setAttributeInternal(index, name, value, NotInSynchronizationOfLazyAttribute);
1496 }
1497
1498 void Element::setAttributeWithoutSynchronization(const QualifiedName& name, const AtomicString& value)
1499 {
1500     unsigned index = elementData() ? elementData()->findAttributeIndexByName(name) : ElementData::attributeNotFound;
1501     setAttributeInternal(index, name, value, NotInSynchronizationOfLazyAttribute);
1502 }
1503
1504 void Element::setSynchronizedLazyAttribute(const QualifiedName& name, const AtomicString& value)
1505 {
1506     unsigned index = elementData() ? elementData()->findAttributeIndexByName(name) : ElementData::attributeNotFound;
1507     setAttributeInternal(index, name, value, InSynchronizationOfLazyAttribute);
1508 }
1509
1510 inline void Element::setAttributeInternal(unsigned index, const QualifiedName& name, const AtomicString& newValue, SynchronizationOfLazyAttribute inSynchronizationOfLazyAttribute)
1511 {
1512     if (newValue.isNull()) {
1513         if (index != ElementData::attributeNotFound)
1514             removeAttributeInternal(index, inSynchronizationOfLazyAttribute);
1515         return;
1516     }
1517
1518     if (index == ElementData::attributeNotFound) {
1519         addAttributeInternal(name, newValue, inSynchronizationOfLazyAttribute);
1520         return;
1521     }
1522
1523     if (inSynchronizationOfLazyAttribute) {
1524         ensureUniqueElementData().attributeAt(index).setValue(newValue);
1525         return;
1526     }
1527
1528     const Attribute& attribute = attributeAt(index);
1529     QualifiedName attributeName = attribute.name();
1530     AtomicString oldValue = attribute.value();
1531
1532     willModifyAttribute(attributeName, oldValue, newValue);
1533
1534     if (newValue != oldValue) {
1535         Style::AttributeChangeInvalidation styleInvalidation(*this, name, oldValue, newValue);
1536         ensureUniqueElementData().attributeAt(index).setValue(newValue);
1537     }
1538
1539     didModifyAttribute(attributeName, oldValue, newValue);
1540 }
1541
1542 static inline AtomicString makeIdForStyleResolution(const AtomicString& value, bool inQuirksMode)
1543 {
1544     if (inQuirksMode)
1545         return value.convertToASCIILowercase();
1546     return value;
1547 }
1548
1549 void Element::attributeChanged(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue, AttributeModificationReason)
1550 {
1551     bool valueIsSameAsBefore = oldValue == newValue;
1552
1553     if (!valueIsSameAsBefore) {
1554         if (name == HTMLNames::idAttr) {
1555             AtomicString oldId = elementData()->idForStyleResolution();
1556             AtomicString newId = makeIdForStyleResolution(newValue, document().inQuirksMode());
1557             if (newId != oldId) {
1558                 Style::IdChangeInvalidation styleInvalidation(*this, oldId, newId);
1559                 elementData()->setIdForStyleResolution(newId);
1560             }
1561
1562             if (!oldValue.isEmpty())
1563                 treeScope().idTargetObserverRegistry().notifyObservers(*oldValue.impl());
1564             if (!newValue.isEmpty())
1565                 treeScope().idTargetObserverRegistry().notifyObservers(*newValue.impl());
1566         } else if (name == classAttr)
1567             classAttributeChanged(newValue);
1568         else if (name == HTMLNames::nameAttr)
1569             elementData()->setHasNameAttribute(!newValue.isNull());
1570         else if (name == HTMLNames::pseudoAttr) {
1571             if (needsStyleInvalidation() && isInShadowTree())
1572                 invalidateStyleForSubtree();
1573         }
1574         else if (name == HTMLNames::slotAttr) {
1575             if (auto* parent = parentElement()) {
1576                 if (auto* shadowRoot = parent->shadowRoot())
1577                     shadowRoot->hostChildElementDidChangeSlotAttribute(*this, oldValue, newValue);
1578             }
1579         }
1580     }
1581
1582     parseAttribute(name, newValue);
1583
1584     document().incDOMTreeVersion();
1585
1586     if (UNLIKELY(isDefinedCustomElement()))
1587         CustomElementReactionQueue::enqueueAttributeChangedCallbackIfNeeded(*this, name, oldValue, newValue);
1588
1589     if (valueIsSameAsBefore)
1590         return;
1591
1592     invalidateNodeListAndCollectionCachesInAncestorsForAttribute(name);
1593
1594     if (AXObjectCache* cache = document().existingAXObjectCache())
1595         cache->deferAttributeChangeIfNeeded(name, this);
1596 }
1597
1598 template <typename CharacterType>
1599 static inline bool classStringHasClassName(const CharacterType* characters, unsigned length)
1600 {
1601     ASSERT(length > 0);
1602
1603     unsigned i = 0;
1604     do {
1605         if (isNotHTMLSpace(characters[i]))
1606             break;
1607         ++i;
1608     } while (i < length);
1609
1610     return i < length;
1611 }
1612
1613 static inline bool classStringHasClassName(const AtomicString& newClassString)
1614 {
1615     unsigned length = newClassString.length();
1616
1617     if (!length)
1618         return false;
1619
1620     if (newClassString.is8Bit())
1621         return classStringHasClassName(newClassString.characters8(), length);
1622     return classStringHasClassName(newClassString.characters16(), length);
1623 }
1624
1625 void Element::classAttributeChanged(const AtomicString& newClassString)
1626 {
1627     // Note: We'll need ElementData, but it doesn't have to be UniqueElementData.
1628     if (!elementData())
1629         ensureUniqueElementData();
1630
1631     bool shouldFoldCase = document().inQuirksMode();
1632     bool newStringHasClasses = classStringHasClassName(newClassString);
1633
1634     auto oldClassNames = elementData()->classNames();
1635     auto newClassNames = newStringHasClasses ? SpaceSplitString(newClassString, shouldFoldCase) : SpaceSplitString();
1636     {
1637         Style::ClassChangeInvalidation styleInvalidation(*this, oldClassNames, newClassNames);
1638         elementData()->setClassNames(newClassNames);
1639     }
1640
1641     if (hasRareData()) {
1642         if (auto* classList = elementRareData()->classList())
1643             classList->associatedAttributeValueChanged(newClassString);
1644     }
1645 }
1646
1647 URL Element::absoluteLinkURL() const
1648 {
1649     if (!isLink())
1650         return URL();
1651
1652     AtomicString linkAttribute;
1653     if (hasTagName(SVGNames::aTag))
1654         linkAttribute = getAttribute(SVGNames::hrefAttr, XLinkNames::hrefAttr);
1655     else
1656         linkAttribute = getAttribute(HTMLNames::hrefAttr);
1657
1658     if (linkAttribute.isEmpty())
1659         return URL();
1660
1661     return document().completeURL(stripLeadingAndTrailingHTMLSpaces(linkAttribute));
1662 }
1663
1664 #if ENABLE(TOUCH_EVENTS)
1665 bool Element::allowsDoubleTapGesture() const
1666 {
1667     if (renderStyle() && renderStyle()->touchAction() != TouchAction::Auto)
1668         return false;
1669
1670     Element* parent = parentElement();
1671     return !parent || parent->allowsDoubleTapGesture();
1672 }
1673 #endif
1674
1675 StyleResolver& Element::styleResolver()
1676 {
1677     if (auto* shadowRoot = containingShadowRoot())
1678         return shadowRoot->styleScope().resolver();
1679
1680     return document().styleScope().resolver();
1681 }
1682
1683 ElementStyle Element::resolveStyle(const RenderStyle* parentStyle)
1684 {
1685     return styleResolver().styleForElement(*this, parentStyle);
1686 }
1687
1688 static void invalidateForSiblingCombinators(Element* sibling)
1689 {
1690     for (; sibling; sibling = sibling->nextElementSibling()) {
1691         if (sibling->styleIsAffectedByPreviousSibling())
1692             sibling->invalidateStyleInternal();
1693         if (sibling->descendantsAffectedByPreviousSibling()) {
1694             for (auto* siblingChild = sibling->firstElementChild(); siblingChild; siblingChild = siblingChild->nextElementSibling())
1695                 siblingChild->invalidateStyleForSubtreeInternal();
1696         }
1697         if (!sibling->affectsNextSiblingElementStyle())
1698             return;
1699     }
1700 }
1701
1702 static void invalidateSiblingsIfNeeded(Element& element)
1703 {
1704     if (!element.affectsNextSiblingElementStyle())
1705         return;
1706     auto* parent = element.parentElement();
1707     if (parent && parent->styleValidity() >= Style::Validity::SubtreeInvalid)
1708         return;
1709
1710     invalidateForSiblingCombinators(element.nextElementSibling());
1711 }
1712
1713 void Element::invalidateStyle()
1714 {
1715     Node::invalidateStyle(Style::Validity::ElementInvalid);
1716     invalidateSiblingsIfNeeded(*this);
1717 }
1718
1719 void Element::invalidateStyleAndLayerComposition()
1720 {
1721     Node::invalidateStyle(Style::Validity::ElementInvalid, Style::InvalidationMode::RecompositeLayer);
1722     invalidateSiblingsIfNeeded(*this);
1723 }
1724
1725 void Element::invalidateStyleForSubtree()
1726 {
1727     Node::invalidateStyle(Style::Validity::SubtreeInvalid);
1728     invalidateSiblingsIfNeeded(*this);
1729 }
1730
1731 void Element::invalidateStyleAndRenderersForSubtree()
1732 {
1733     Node::invalidateStyle(Style::Validity::SubtreeAndRenderersInvalid);
1734     invalidateSiblingsIfNeeded(*this);
1735 }
1736
1737 void Element::invalidateStyleInternal()
1738 {
1739     Node::invalidateStyle(Style::Validity::ElementInvalid);
1740 }
1741
1742 void Element::invalidateStyleForSubtreeInternal()
1743 {
1744     Node::invalidateStyle(Style::Validity::SubtreeInvalid);
1745 }
1746
1747 bool Element::hasDisplayContents() const
1748 {
1749     if (!hasRareData())
1750         return false;
1751
1752     const RenderStyle* style = elementRareData()->computedStyle();
1753     return style && style->display() == DisplayType::Contents;
1754 }
1755
1756 void Element::storeDisplayContentsStyle(std::unique_ptr<RenderStyle> style)
1757 {
1758     ASSERT(style && style->display() == DisplayType::Contents);
1759     ASSERT(!renderer() || isPseudoElement());
1760     ensureElementRareData().setComputedStyle(WTFMove(style));
1761 }
1762
1763 // Returns true is the given attribute is an event handler.
1764 // We consider an event handler any attribute that begins with "on".
1765 // It is a simple solution that has the advantage of not requiring any
1766 // code or configuration change if a new event handler is defined.
1767
1768 bool Element::isEventHandlerAttribute(const Attribute& attribute) const
1769 {
1770     return attribute.name().namespaceURI().isNull() && attribute.name().localName().startsWith("on");
1771 }
1772
1773 bool Element::isJavaScriptURLAttribute(const Attribute& attribute) const
1774 {
1775     return isURLAttribute(attribute) && WTF::protocolIsJavaScript(stripLeadingAndTrailingHTMLSpaces(attribute.value()));
1776 }
1777
1778 void Element::stripScriptingAttributes(Vector<Attribute>& attributeVector) const
1779 {
1780     attributeVector.removeAllMatching([this](auto& attribute) -> bool {
1781         return this->isEventHandlerAttribute(attribute)
1782             || this->isJavaScriptURLAttribute(attribute)
1783             || this->isHTMLContentAttribute(attribute);
1784     });
1785 }
1786
1787 void Element::parserSetAttributes(const Vector<Attribute>& attributeVector)
1788 {
1789     ASSERT(!isConnected());
1790     ASSERT(!parentNode());
1791     ASSERT(!m_elementData);
1792
1793     if (!attributeVector.isEmpty()) {
1794         if (document().sharedObjectPool())
1795             m_elementData = document().sharedObjectPool()->cachedShareableElementDataWithAttributes(attributeVector);
1796         else
1797             m_elementData = ShareableElementData::createWithAttributes(attributeVector);
1798
1799     }
1800
1801     parserDidSetAttributes();
1802
1803     // Use attributeVector instead of m_elementData because attributeChanged might modify m_elementData.
1804     for (const auto& attribute : attributeVector)
1805         attributeChanged(attribute.name(), nullAtom(), attribute.value(), ModifiedDirectly);
1806 }
1807
1808 void Element::parserDidSetAttributes()
1809 {
1810 }
1811
1812 void Element::didMoveToNewDocument(Document& oldDocument, Document& newDocument)
1813 {
1814     ASSERT_WITH_SECURITY_IMPLICATION(&document() == &newDocument);
1815
1816     if (oldDocument.inQuirksMode() != document().inQuirksMode()) {
1817         // ElementData::m_classNames or ElementData::m_idForStyleResolution need to be updated with the right case.
1818         if (hasID())
1819             attributeChanged(idAttr, nullAtom(), getIdAttribute());
1820         if (hasClass())
1821             attributeChanged(classAttr, nullAtom(), getAttribute(classAttr));
1822     }
1823
1824     if (UNLIKELY(isDefinedCustomElement()))
1825         CustomElementReactionQueue::enqueueAdoptedCallbackIfNeeded(*this, oldDocument, newDocument);
1826
1827 #if ENABLE(INTERSECTION_OBSERVER)
1828     if (auto* observerData = intersectionObserverData()) {
1829         for (const auto& observer : observerData->observers) {
1830             if (observer->hasObservationTargets()) {
1831                 oldDocument.removeIntersectionObserver(*observer);
1832                 newDocument.addIntersectionObserver(*observer);
1833             }
1834         }
1835     }
1836 #endif
1837 }
1838
1839 bool Element::hasAttributes() const
1840 {
1841     synchronizeAllAttributes();
1842     return elementData() && elementData()->length();
1843 }
1844
1845 bool Element::hasEquivalentAttributes(const Element* other) const
1846 {
1847     synchronizeAllAttributes();
1848     other->synchronizeAllAttributes();
1849     if (elementData() == other->elementData())
1850         return true;
1851     if (elementData())
1852         return elementData()->isEquivalent(other->elementData());
1853     if (other->elementData())
1854         return other->elementData()->isEquivalent(elementData());
1855     return true;
1856 }
1857
1858 String Element::nodeName() const
1859 {
1860     return m_tagName.toString();
1861 }
1862
1863 String Element::nodeNamePreservingCase() const
1864 {
1865     return m_tagName.toString();
1866 }
1867
1868 ExceptionOr<void> Element::setPrefix(const AtomicString& prefix)
1869 {
1870     auto result = checkSetPrefix(prefix);
1871     if (result.hasException())
1872         return result.releaseException();
1873
1874     m_tagName.setPrefix(prefix.isEmpty() ? nullAtom() : prefix);
1875     return { };
1876 }
1877
1878 const AtomicString& Element::imageSourceURL() const
1879 {
1880     return attributeWithoutSynchronization(srcAttr);
1881 }
1882
1883 bool Element::rendererIsNeeded(const RenderStyle& style)
1884 {
1885     return style.display() != DisplayType::None && style.display() != DisplayType::Contents;
1886 }
1887
1888 RenderPtr<RenderElement> Element::createElementRenderer(RenderStyle&& style, const RenderTreePosition&)
1889 {
1890     return RenderElement::createFor(*this, WTFMove(style));
1891 }
1892
1893 Node::InsertedIntoAncestorResult Element::insertedIntoAncestor(InsertionType insertionType, ContainerNode& parentOfInsertedTree)
1894 {
1895     ContainerNode::insertedIntoAncestor(insertionType, parentOfInsertedTree);
1896
1897 #if ENABLE(FULLSCREEN_API)
1898     if (containsFullScreenElement() && parentElement() && !parentElement()->containsFullScreenElement())
1899         setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(true);
1900 #endif
1901
1902     if (parentNode() == &parentOfInsertedTree) {
1903         if (auto* shadowRoot = parentNode()->shadowRoot())
1904             shadowRoot->hostChildElementDidChange(*this);
1905     }
1906
1907     if (!parentOfInsertedTree.isInTreeScope())
1908         return InsertedIntoAncestorResult::Done;
1909
1910     bool becomeConnected = insertionType.connectedToDocument;
1911     TreeScope* newScope = &parentOfInsertedTree.treeScope();
1912     HTMLDocument* newDocument = becomeConnected && is<HTMLDocument>(newScope->documentScope()) ? &downcast<HTMLDocument>(newScope->documentScope()) : nullptr;
1913     if (!insertionType.treeScopeChanged)
1914         newScope = nullptr;
1915
1916     const AtomicString& idValue = getIdAttribute();
1917     if (!idValue.isNull()) {
1918         if (newScope)
1919             updateIdForTreeScope(*newScope, nullAtom(), idValue);
1920         if (newDocument)
1921             updateIdForDocument(*newDocument, nullAtom(), idValue, AlwaysUpdateHTMLDocumentNamedItemMaps);
1922     }
1923
1924     const AtomicString& nameValue = getNameAttribute();
1925     if (!nameValue.isNull()) {
1926         if (newScope)
1927             updateNameForTreeScope(*newScope, nullAtom(), nameValue);
1928         if (newDocument)
1929             updateNameForDocument(*newDocument, nullAtom(), nameValue);
1930     }
1931
1932     if (newScope && hasTagName(labelTag)) {
1933         if (newScope->shouldCacheLabelsByForAttribute())
1934             updateLabel(*newScope, nullAtom(), attributeWithoutSynchronization(forAttr));
1935     }
1936
1937     if (becomeConnected) {
1938         if (UNLIKELY(isCustomElementUpgradeCandidate())) {
1939             ASSERT(isConnected());
1940             CustomElementReactionQueue::enqueueElementUpgradeIfDefined(*this);
1941         }
1942         if (UNLIKELY(isDefinedCustomElement()))
1943             CustomElementReactionQueue::enqueueConnectedCallbackIfNeeded(*this);
1944     }
1945
1946     if (UNLIKELY(hasTagName(articleTag) && newDocument))
1947         newDocument->registerArticleElement(*this);
1948
1949     return InsertedIntoAncestorResult::Done;
1950 }
1951
1952 void Element::removedFromAncestor(RemovalType removalType, ContainerNode& oldParentOfRemovedTree)
1953 {
1954 #if ENABLE(FULLSCREEN_API)
1955     if (containsFullScreenElement())
1956         setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false);
1957 #endif
1958 #if ENABLE(POINTER_LOCK)
1959     if (document().page())
1960         document().page()->pointerLockController().elementRemoved(*this);
1961 #endif
1962
1963     setSavedLayerScrollPosition(ScrollPosition());
1964
1965     if (oldParentOfRemovedTree.isInTreeScope()) {
1966         TreeScope* oldScope = &oldParentOfRemovedTree.treeScope();
1967         Document* oldDocument = removalType.disconnectedFromDocument ? &oldScope->documentScope() : nullptr;
1968         HTMLDocument* oldHTMLDocument = oldDocument && is<HTMLDocument>(*oldDocument) ? &downcast<HTMLDocument>(*oldDocument) : nullptr;
1969         if (!removalType.treeScopeChanged)
1970             oldScope = nullptr;
1971
1972         const AtomicString& idValue = getIdAttribute();
1973         if (!idValue.isNull()) {
1974             if (oldScope)
1975                 updateIdForTreeScope(*oldScope, idValue, nullAtom());
1976             if (oldHTMLDocument)
1977                 updateIdForDocument(*oldHTMLDocument, idValue, nullAtom(), AlwaysUpdateHTMLDocumentNamedItemMaps);
1978         }
1979
1980         const AtomicString& nameValue = getNameAttribute();
1981         if (!nameValue.isNull()) {
1982             if (oldScope)
1983                 updateNameForTreeScope(*oldScope, nameValue, nullAtom());
1984             if (oldHTMLDocument)
1985                 updateNameForDocument(*oldHTMLDocument, nameValue, nullAtom());
1986         }
1987
1988         if (oldScope && hasTagName(labelTag)) {
1989             if (oldScope->shouldCacheLabelsByForAttribute())
1990                 updateLabel(*oldScope, attributeWithoutSynchronization(forAttr), nullAtom());
1991         }
1992
1993         if (oldDocument) {
1994             if (oldDocument->cssTarget() == this)
1995                 oldDocument->setCSSTarget(nullptr);
1996             if (UNLIKELY(hasTagName(articleTag)))
1997                 oldDocument->unregisterArticleElement(*this);
1998         }
1999
2000         if (removalType.disconnectedFromDocument && UNLIKELY(isDefinedCustomElement()))
2001             CustomElementReactionQueue::enqueueDisconnectedCallbackIfNeeded(*this);
2002     }
2003
2004     if (!parentNode()) {
2005         if (auto* shadowRoot = oldParentOfRemovedTree.shadowRoot())
2006             shadowRoot->hostChildElementDidChange(*this);
2007     }
2008
2009     clearBeforePseudoElement();
2010     clearAfterPseudoElement();
2011
2012     ContainerNode::removedFromAncestor(removalType, oldParentOfRemovedTree);
2013
2014     if (hasPendingResources())
2015         document().accessSVGExtensions().removeElementFromPendingResources(this);
2016
2017     RefPtr<Frame> frame = document().frame();
2018     if (auto* timeline = document().existingTimeline())
2019         timeline->elementWasRemoved(*this);
2020     if (frame)
2021         frame->animation().cancelAnimations(*this);
2022
2023 #if PLATFORM(MAC)
2024     if (frame && frame->page())
2025         frame->page()->removeLatchingStateForTarget(*this);
2026 #endif
2027 }
2028
2029 ShadowRoot* Element::shadowRoot() const
2030 {
2031     return hasRareData() ? elementRareData()->shadowRoot() : nullptr;
2032 }
2033
2034 void Element::addShadowRoot(Ref<ShadowRoot>&& newShadowRoot)
2035 {
2036     ASSERT(!newShadowRoot->hasChildNodes());
2037     ASSERT(!shadowRoot());
2038
2039     ShadowRoot& shadowRoot = newShadowRoot;
2040     {
2041         ScriptDisallowedScope::InMainThread scriptDisallowedScope;
2042         if (renderer())
2043             RenderTreeUpdater::tearDownRenderers(*this);
2044
2045         ensureElementRareData().setShadowRoot(WTFMove(newShadowRoot));
2046
2047         shadowRoot.setHost(this);
2048         shadowRoot.setParentTreeScope(treeScope());
2049
2050 #if !ASSERT_DISABLED
2051         ASSERT(notifyChildNodeInserted(*this, shadowRoot).isEmpty());
2052 #else
2053         notifyChildNodeInserted(*this, shadowRoot);
2054 #endif
2055
2056         invalidateStyleAndRenderersForSubtree();
2057     }
2058
2059     if (shadowRoot.mode() == ShadowRootMode::UserAgent)
2060         didAddUserAgentShadowRoot(shadowRoot);
2061
2062     InspectorInstrumentation::didPushShadowRoot(*this, shadowRoot);
2063 }
2064
2065 void Element::removeShadowRoot()
2066 {
2067     RefPtr<ShadowRoot> oldRoot = shadowRoot();
2068     if (!oldRoot)
2069         return;
2070
2071     InspectorInstrumentation::willPopShadowRoot(*this, *oldRoot);
2072     document().adjustFocusedNodeOnNodeRemoval(*oldRoot);
2073
2074     ASSERT(!oldRoot->renderer());
2075
2076     elementRareData()->clearShadowRoot();
2077
2078     oldRoot->setHost(nullptr);
2079     oldRoot->setParentTreeScope(document());
2080 }
2081
2082 static bool canAttachAuthorShadowRoot(const Element& element)
2083 {
2084     static NeverDestroyed<HashSet<AtomicString>> tagNames = [] {
2085         static const HTMLQualifiedName* const tagList[] = {
2086             &articleTag.get(),
2087             &asideTag.get(),
2088             &blockquoteTag.get(),
2089             &bodyTag.get(),
2090             &divTag.get(),
2091             &footerTag.get(),
2092             &h1Tag.get(),
2093             &h2Tag.get(),
2094             &h3Tag.get(),
2095             &h4Tag.get(),
2096             &h5Tag.get(),
2097             &h6Tag.get(),
2098             &headerTag.get(),
2099             &navTag.get(),
2100             &pTag.get(),
2101             &sectionTag.get(),
2102             &spanTag.get()
2103         };
2104         HashSet<AtomicString> set;
2105         for (auto& name : tagList)
2106             set.add(name->localName());
2107         return set;
2108     }();
2109
2110     if (!is<HTMLElement>(element))
2111         return false;
2112
2113     const auto& localName = element.localName();
2114     return tagNames.get().contains(localName) || Document::validateCustomElementName(localName) == CustomElementNameValidationStatus::Valid;
2115 }
2116
2117 ExceptionOr<ShadowRoot&> Element::attachShadow(const ShadowRootInit& init)
2118 {
2119     if (!canAttachAuthorShadowRoot(*this))
2120         return Exception { NotSupportedError };
2121     if (shadowRoot())
2122         return Exception { InvalidStateError };
2123     if (init.mode == ShadowRootMode::UserAgent)
2124         return Exception { TypeError };
2125     auto shadow = ShadowRoot::create(document(), init.mode);
2126     auto& result = shadow.get();
2127     addShadowRoot(WTFMove(shadow));
2128     return result;
2129 }
2130
2131 ShadowRoot* Element::shadowRootForBindings(JSC::ExecState& state) const
2132 {
2133     auto* shadow = shadowRoot();
2134     if (!shadow)
2135         return nullptr;
2136     if (shadow->mode() == ShadowRootMode::Open)
2137         return shadow;
2138     if (JSC::jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject())->world().shadowRootIsAlwaysOpen())
2139         return shadow;
2140     return nullptr;
2141 }
2142
2143 RefPtr<ShadowRoot> Element::userAgentShadowRoot() const
2144 {
2145     ASSERT(!shadowRoot() || shadowRoot()->mode() == ShadowRootMode::UserAgent);
2146     return shadowRoot();
2147 }
2148
2149 ShadowRoot& Element::ensureUserAgentShadowRoot()
2150 {
2151     if (auto shadow = userAgentShadowRoot())
2152         return *shadow;
2153     auto newShadow = ShadowRoot::create(document(), ShadowRootMode::UserAgent);
2154     ShadowRoot& shadow = newShadow;
2155     addShadowRoot(WTFMove(newShadow));
2156     return shadow;
2157 }
2158
2159 void Element::setIsDefinedCustomElement(JSCustomElementInterface& elementInterface)
2160 {
2161     clearFlag(IsEditingTextOrUndefinedCustomElementFlag);
2162     setFlag(IsCustomElement);
2163     auto& data = ensureElementRareData();
2164     if (!data.customElementReactionQueue())
2165         data.setCustomElementReactionQueue(std::make_unique<CustomElementReactionQueue>(elementInterface));
2166     invalidateStyleForSubtree();
2167     InspectorInstrumentation::didChangeCustomElementState(*this);
2168 }
2169
2170 void Element::setIsFailedCustomElement(JSCustomElementInterface&)
2171 {
2172     ASSERT(isUndefinedCustomElement());
2173     ASSERT(getFlag(IsEditingTextOrUndefinedCustomElementFlag));
2174     clearFlag(IsCustomElement);
2175
2176     if (hasRareData()) {
2177         // Clear the queue instead of deleting it since this function can be called inside CustomElementReactionQueue::invokeAll during upgrades.
2178         if (auto* queue = elementRareData()->customElementReactionQueue())
2179             queue->clear();
2180     }
2181     InspectorInstrumentation::didChangeCustomElementState(*this);
2182 }
2183
2184 void Element::setIsCustomElementUpgradeCandidate()
2185 {
2186     ASSERT(!getFlag(IsCustomElement));
2187     setFlag(IsCustomElement);
2188     setFlag(IsEditingTextOrUndefinedCustomElementFlag);
2189     InspectorInstrumentation::didChangeCustomElementState(*this);
2190 }
2191
2192 void Element::enqueueToUpgrade(JSCustomElementInterface& elementInterface)
2193 {
2194     ASSERT(!isDefinedCustomElement() && !isFailedCustomElement());
2195     setFlag(IsCustomElement);
2196     setFlag(IsEditingTextOrUndefinedCustomElementFlag);
2197     InspectorInstrumentation::didChangeCustomElementState(*this);
2198
2199     auto& data = ensureElementRareData();
2200     bool alreadyScheduledToUpgrade = data.customElementReactionQueue();
2201     if (!alreadyScheduledToUpgrade)
2202         data.setCustomElementReactionQueue(std::make_unique<CustomElementReactionQueue>(elementInterface));
2203     data.customElementReactionQueue()->enqueueElementUpgrade(*this, alreadyScheduledToUpgrade);
2204 }
2205
2206 CustomElementReactionQueue* Element::reactionQueue() const
2207 {
2208     ASSERT(isDefinedCustomElement() || isCustomElementUpgradeCandidate());
2209     if (!hasRareData())
2210         return nullptr;
2211     return elementRareData()->customElementReactionQueue();
2212 }
2213
2214 const AtomicString& Element::shadowPseudoId() const
2215 {
2216     return pseudo();
2217 }
2218
2219 bool Element::childTypeAllowed(NodeType type) const
2220 {
2221     switch (type) {
2222     case ELEMENT_NODE:
2223     case TEXT_NODE:
2224     case COMMENT_NODE:
2225     case PROCESSING_INSTRUCTION_NODE:
2226     case CDATA_SECTION_NODE:
2227         return true;
2228     default:
2229         break;
2230     }
2231     return false;
2232 }
2233
2234 static void checkForEmptyStyleChange(Element& element)
2235 {
2236     if (element.styleAffectedByEmpty()) {
2237         auto* style = element.renderStyle();
2238         if (!style || (!style->emptyState() || element.hasChildNodes()))
2239             element.invalidateStyleForSubtree();
2240     }
2241 }
2242
2243
2244 static void invalidateForForwardPositionalRules(Element& parent, Element* elementAfterChange)
2245 {
2246     bool childrenAffected = parent.childrenAffectedByForwardPositionalRules();
2247     bool descendantsAffected = parent.descendantsAffectedByForwardPositionalRules();
2248
2249     if (!childrenAffected && !descendantsAffected)
2250         return;
2251
2252     for (auto* sibling = elementAfterChange; sibling; sibling = sibling->nextElementSibling()) {
2253         if (childrenAffected)
2254             sibling->invalidateStyleInternal();
2255         if (descendantsAffected) {
2256             for (auto* siblingChild = sibling->firstElementChild(); siblingChild; siblingChild = siblingChild->nextElementSibling())
2257                 siblingChild->invalidateStyleForSubtreeInternal();
2258         }
2259     }
2260 }
2261
2262 static void invalidateForBackwardPositionalRules(Element& parent, Element* elementBeforeChange)
2263 {
2264     bool childrenAffected = parent.childrenAffectedByBackwardPositionalRules();
2265     bool descendantsAffected = parent.descendantsAffectedByBackwardPositionalRules();
2266
2267     if (!childrenAffected && !descendantsAffected)
2268         return;
2269
2270     for (auto* sibling = elementBeforeChange; sibling; sibling = sibling->previousElementSibling()) {
2271         if (childrenAffected)
2272             sibling->invalidateStyleInternal();
2273         if (descendantsAffected) {
2274             for (auto* siblingChild = sibling->firstElementChild(); siblingChild; siblingChild = siblingChild->nextElementSibling())
2275                 siblingChild->invalidateStyleForSubtreeInternal();
2276         }
2277     }
2278 }
2279
2280 enum SiblingCheckType { FinishedParsingChildren, SiblingElementRemoved, Other };
2281
2282 static void checkForSiblingStyleChanges(Element& parent, SiblingCheckType checkType, Element* elementBeforeChange, Element* elementAfterChange)
2283 {
2284     // :empty selector.
2285     checkForEmptyStyleChange(parent);
2286
2287     if (parent.styleValidity() >= Style::Validity::SubtreeInvalid)
2288         return;
2289
2290     // :first-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
2291     // In the DOM case, we only need to do something if |afterChange| is not 0.
2292     // |afterChange| is 0 in the parser case, so it works out that we'll skip this block.
2293     if (parent.childrenAffectedByFirstChildRules() && elementAfterChange) {
2294         // Find our new first child.
2295         RefPtr<Element> newFirstElement = ElementTraversal::firstChild(parent);
2296         // Find the first element node following |afterChange|
2297
2298         // This is the insert/append case.
2299         if (newFirstElement != elementAfterChange) {
2300             auto* style = elementAfterChange->renderStyle();
2301             if (!style || style->firstChildState())
2302                 elementAfterChange->invalidateStyleForSubtreeInternal();
2303         }
2304
2305         // We also have to handle node removal.
2306         if (checkType == SiblingElementRemoved && newFirstElement == elementAfterChange && newFirstElement) {
2307             auto* style = newFirstElement->renderStyle();
2308             if (!style || !style->firstChildState())
2309                 newFirstElement->invalidateStyleForSubtreeInternal();
2310         }
2311     }
2312
2313     // :last-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
2314     // In the DOM case, we only need to do something if |afterChange| is not 0.
2315     if (parent.childrenAffectedByLastChildRules() && elementBeforeChange) {
2316         // Find our new last child.
2317         RefPtr<Element> newLastElement = ElementTraversal::lastChild(parent);
2318
2319         if (newLastElement != elementBeforeChange) {
2320             auto* style = elementBeforeChange->renderStyle();
2321             if (!style || style->lastChildState())
2322                 elementBeforeChange->invalidateStyleForSubtreeInternal();
2323         }
2324
2325         // We also have to handle node removal.  The parser callback case is similar to node removal as well in that we need to change the last child
2326         // to match now.
2327         if ((checkType == SiblingElementRemoved || checkType == FinishedParsingChildren) && newLastElement == elementBeforeChange && newLastElement) {
2328             auto* style = newLastElement->renderStyle();
2329             if (!style || !style->lastChildState())
2330                 newLastElement->invalidateStyleForSubtreeInternal();
2331         }
2332     }
2333
2334     invalidateForSiblingCombinators(elementAfterChange);
2335
2336     invalidateForForwardPositionalRules(parent, elementAfterChange);
2337     invalidateForBackwardPositionalRules(parent, elementBeforeChange);
2338 }
2339
2340 void Element::childrenChanged(const ChildChange& change)
2341 {
2342     ContainerNode::childrenChanged(change);
2343     if (change.source == ChildChangeSource::Parser)
2344         checkForEmptyStyleChange(*this);
2345     else {
2346         SiblingCheckType checkType = change.type == ElementRemoved ? SiblingElementRemoved : Other;
2347         checkForSiblingStyleChanges(*this, checkType, change.previousSiblingElement, change.nextSiblingElement);
2348     }
2349
2350     if (ShadowRoot* shadowRoot = this->shadowRoot()) {
2351         switch (change.type) {
2352         case ElementInserted:
2353         case ElementRemoved:
2354             // For elements, we notify shadowRoot in Element::insertedIntoAncestor and Element::removedFromAncestor.
2355             break;
2356         case AllChildrenRemoved:
2357         case AllChildrenReplaced:
2358             shadowRoot->didRemoveAllChildrenOfShadowHost();
2359             break;
2360         case TextInserted:
2361         case TextRemoved:
2362         case TextChanged:
2363             shadowRoot->didChangeDefaultSlot();
2364             break;
2365         case NonContentsChildInserted:
2366         case NonContentsChildRemoved:
2367             break;
2368         }
2369     }
2370 }
2371
2372 void Element::setAttributeEventListener(const AtomicString& eventType, const QualifiedName& attributeName, const AtomicString& attributeValue)
2373 {
2374     setAttributeEventListener(eventType, JSLazyEventListener::create(*this, attributeName, attributeValue), mainThreadNormalWorld());
2375 }
2376
2377 void Element::removeAllEventListeners()
2378 {
2379     ContainerNode::removeAllEventListeners();
2380     if (ShadowRoot* shadowRoot = this->shadowRoot())
2381         shadowRoot->removeAllEventListeners();
2382 }
2383
2384 void Element::beginParsingChildren()
2385 {
2386     clearIsParsingChildrenFinished();
2387 }
2388
2389 void Element::finishParsingChildren()
2390 {
2391     ContainerNode::finishParsingChildren();
2392     setIsParsingChildrenFinished();
2393     checkForSiblingStyleChanges(*this, FinishedParsingChildren, ElementTraversal::lastChild(*this), nullptr);
2394 }
2395
2396 #if ENABLE(TREE_DEBUGGING)
2397 void Element::formatForDebugger(char* buffer, unsigned length) const
2398 {
2399     StringBuilder result;
2400     String s;
2401
2402     result.append(nodeName());
2403
2404     s = getIdAttribute();
2405     if (s.length() > 0) {
2406         if (result.length() > 0)
2407             result.appendLiteral("; ");
2408         result.appendLiteral("id=");
2409         result.append(s);
2410     }
2411
2412     s = getAttribute(classAttr);
2413     if (s.length() > 0) {
2414         if (result.length() > 0)
2415             result.appendLiteral("; ");
2416         result.appendLiteral("class=");
2417         result.append(s);
2418     }
2419
2420     strncpy(buffer, result.toString().utf8().data(), length - 1);
2421 }
2422 #endif
2423
2424 const Vector<RefPtr<Attr>>& Element::attrNodeList()
2425 {
2426     ASSERT(hasSyntheticAttrChildNodes());
2427     return *attrNodeListForElement(*this);
2428 }
2429
2430 void Element::attachAttributeNodeIfNeeded(Attr& attrNode)
2431 {
2432     ASSERT(!attrNode.ownerElement() || attrNode.ownerElement() == this);
2433     if (attrNode.ownerElement() == this)
2434         return;
2435
2436     ScriptDisallowedScope::InMainThread scriptDisallowedScope;
2437
2438     attrNode.attachToElement(*this);
2439     ensureAttrNodeListForElement(*this).append(&attrNode);
2440 }
2441
2442 ExceptionOr<RefPtr<Attr>> Element::setAttributeNode(Attr& attrNode)
2443 {
2444     RefPtr<Attr> oldAttrNode = attrIfExists(attrNode.localName(), shouldIgnoreAttributeCase(*this));
2445     if (oldAttrNode.get() == &attrNode)
2446         return WTFMove(oldAttrNode);
2447
2448     // InUseAttributeError: Raised if node is an Attr that is already an attribute of another Element object.
2449     // The DOM user must explicitly clone Attr nodes to re-use them in other elements.
2450     if (attrNode.ownerElement() && attrNode.ownerElement() != this)
2451         return Exception { InUseAttributeError };
2452
2453     {
2454         ScriptDisallowedScope::InMainThread scriptDisallowedScope;
2455         synchronizeAllAttributes();
2456     }
2457
2458     auto& elementData = ensureUniqueElementData();
2459
2460     auto existingAttributeIndex = elementData.findAttributeIndexByName(attrNode.localName(), shouldIgnoreAttributeCase(*this));
2461
2462     // Attr::value() will return its 'm_standaloneValue' member any time its Element is set to nullptr. We need to cache this value
2463     // before making changes to attrNode's Element connections.
2464     auto attrNodeValue = attrNode.value();
2465
2466     if (existingAttributeIndex == ElementData::attributeNotFound) {
2467         attachAttributeNodeIfNeeded(attrNode);
2468         setAttributeInternal(elementData.findAttributeIndexByName(attrNode.qualifiedName()), attrNode.qualifiedName(), attrNodeValue, NotInSynchronizationOfLazyAttribute);
2469     } else {
2470         const Attribute& attribute = attributeAt(existingAttributeIndex);
2471         if (oldAttrNode)
2472             detachAttrNodeFromElementWithValue(oldAttrNode.get(), attribute.value());
2473         else
2474             oldAttrNode = Attr::create(document(), attrNode.qualifiedName(), attribute.value());
2475
2476         attachAttributeNodeIfNeeded(attrNode);
2477
2478         if (attribute.name().matches(attrNode.qualifiedName()))
2479             setAttributeInternal(existingAttributeIndex, attrNode.qualifiedName(), attrNodeValue, NotInSynchronizationOfLazyAttribute);
2480         else {
2481             removeAttributeInternal(existingAttributeIndex, NotInSynchronizationOfLazyAttribute);
2482             setAttributeInternal(ensureUniqueElementData().findAttributeIndexByName(attrNode.qualifiedName()), attrNode.qualifiedName(), attrNodeValue, NotInSynchronizationOfLazyAttribute);
2483         }
2484     }
2485
2486     return WTFMove(oldAttrNode);
2487 }
2488
2489 ExceptionOr<RefPtr<Attr>> Element::setAttributeNodeNS(Attr& attrNode)
2490 {
2491     RefPtr<Attr> oldAttrNode = attrIfExists(attrNode.qualifiedName());
2492     if (oldAttrNode.get() == &attrNode)
2493         return WTFMove(oldAttrNode);
2494
2495     // InUseAttributeError: Raised if node is an Attr that is already an attribute of another Element object.
2496     // The DOM user must explicitly clone Attr nodes to re-use them in other elements.
2497     if (attrNode.ownerElement() && attrNode.ownerElement() != this)
2498         return Exception { InUseAttributeError };
2499
2500     // Attr::value() will return its 'm_standaloneValue' member any time its Element is set to nullptr. We need to cache this value
2501     // before making changes to attrNode's Element connections.
2502     auto attrNodeValue = attrNode.value();
2503     unsigned index = 0;
2504     {
2505         ScriptDisallowedScope::InMainThread scriptDisallowedScope;
2506         synchronizeAllAttributes();
2507         auto& elementData = ensureUniqueElementData();
2508
2509         index = elementData.findAttributeIndexByName(attrNode.qualifiedName());
2510
2511         if (index != ElementData::attributeNotFound) {
2512             if (oldAttrNode)
2513                 detachAttrNodeFromElementWithValue(oldAttrNode.get(), elementData.attributeAt(index).value());
2514             else
2515                 oldAttrNode = Attr::create(document(), attrNode.qualifiedName(), elementData.attributeAt(index).value());
2516         }
2517     }
2518
2519     attachAttributeNodeIfNeeded(attrNode);
2520     setAttributeInternal(index, attrNode.qualifiedName(), attrNodeValue, NotInSynchronizationOfLazyAttribute);
2521
2522     return WTFMove(oldAttrNode);
2523 }
2524
2525 ExceptionOr<Ref<Attr>> Element::removeAttributeNode(Attr& attr)
2526 {
2527     if (attr.ownerElement() != this)
2528         return Exception { NotFoundError };
2529
2530     ASSERT(&document() == &attr.document());
2531
2532     synchronizeAllAttributes();
2533
2534     if (!m_elementData)
2535         return Exception { NotFoundError };
2536
2537     auto existingAttributeIndex = m_elementData->findAttributeIndexByName(attr.qualifiedName());
2538     if (existingAttributeIndex == ElementData::attributeNotFound)
2539         return Exception { NotFoundError };
2540
2541     Ref<Attr> oldAttrNode { attr };
2542
2543     detachAttrNodeFromElementWithValue(&attr, m_elementData->attributeAt(existingAttributeIndex).value());
2544     removeAttributeInternal(existingAttributeIndex, NotInSynchronizationOfLazyAttribute);
2545
2546     return WTFMove(oldAttrNode);
2547 }
2548
2549 ExceptionOr<QualifiedName> Element::parseAttributeName(const AtomicString& namespaceURI, const AtomicString& qualifiedName)
2550 {
2551     auto parseResult = Document::parseQualifiedName(namespaceURI, qualifiedName);
2552     if (parseResult.hasException())
2553         return parseResult.releaseException();
2554     QualifiedName parsedAttributeName { parseResult.releaseReturnValue() };
2555     if (!Document::hasValidNamespaceForAttributes(parsedAttributeName))
2556         return Exception { NamespaceError };
2557     return WTFMove(parsedAttributeName);
2558 }
2559
2560 ExceptionOr<void> Element::setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value)
2561 {
2562     auto result = parseAttributeName(namespaceURI, qualifiedName);
2563     if (result.hasException())
2564         return result.releaseException();
2565     setAttribute(result.releaseReturnValue(), value);
2566     return { };
2567 }
2568
2569 void Element::removeAttributeInternal(unsigned index, SynchronizationOfLazyAttribute inSynchronizationOfLazyAttribute)
2570 {
2571     ASSERT_WITH_SECURITY_IMPLICATION(index < attributeCount());
2572
2573     UniqueElementData& elementData = ensureUniqueElementData();
2574
2575     QualifiedName name = elementData.attributeAt(index).name();
2576     AtomicString valueBeingRemoved = elementData.attributeAt(index).value();
2577
2578     if (RefPtr<Attr> attrNode = attrIfExists(name))
2579         detachAttrNodeFromElementWithValue(attrNode.get(), elementData.attributeAt(index).value());
2580
2581     if (inSynchronizationOfLazyAttribute) {
2582         elementData.removeAttribute(index);
2583         return;
2584     }
2585
2586     ASSERT(!valueBeingRemoved.isNull());
2587     willModifyAttribute(name, valueBeingRemoved, nullAtom());
2588     {
2589         Style::AttributeChangeInvalidation styleInvalidation(*this, name, valueBeingRemoved, nullAtom());
2590         elementData.removeAttribute(index);
2591     }
2592
2593     didRemoveAttribute(name, valueBeingRemoved);
2594 }
2595
2596 void Element::addAttributeInternal(const QualifiedName& name, const AtomicString& value, SynchronizationOfLazyAttribute inSynchronizationOfLazyAttribute)
2597 {
2598     if (inSynchronizationOfLazyAttribute) {
2599         ensureUniqueElementData().addAttribute(name, value);
2600         return;
2601     }
2602
2603     willModifyAttribute(name, nullAtom(), value);
2604     {
2605         Style::AttributeChangeInvalidation styleInvalidation(*this, name, nullAtom(), value);
2606         ensureUniqueElementData().addAttribute(name, value);
2607     }
2608     didAddAttribute(name, value);
2609 }
2610
2611 bool Element::removeAttribute(const AtomicString& qualifiedName)
2612 {
2613     if (!elementData())
2614         return false;
2615
2616     AtomicString caseAdjustedQualifiedName = shouldIgnoreAttributeCase(*this) ? qualifiedName.convertToASCIILowercase() : qualifiedName;
2617     unsigned index = elementData()->findAttributeIndexByName(caseAdjustedQualifiedName, false);
2618     if (index == ElementData::attributeNotFound) {
2619         if (UNLIKELY(caseAdjustedQualifiedName == styleAttr) && elementData()->styleAttributeIsDirty() && is<StyledElement>(*this))
2620             downcast<StyledElement>(*this).removeAllInlineStyleProperties();
2621         return false;
2622     }
2623
2624     removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute);
2625     return true;
2626 }
2627
2628 bool Element::removeAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName)
2629 {
2630     return removeAttribute(QualifiedName(nullAtom(), localName, namespaceURI));
2631 }
2632
2633 RefPtr<Attr> Element::getAttributeNode(const AtomicString& qualifiedName)
2634 {
2635     if (!elementData())
2636         return nullptr;
2637     synchronizeAttribute(qualifiedName);
2638     const Attribute* attribute = elementData()->findAttributeByName(qualifiedName, shouldIgnoreAttributeCase(*this));
2639     if (!attribute)
2640         return nullptr;
2641     return ensureAttr(attribute->name());
2642 }
2643
2644 RefPtr<Attr> Element::getAttributeNodeNS(const AtomicString& namespaceURI, const AtomicString& localName)
2645 {
2646     if (!elementData())
2647         return 0;
2648     QualifiedName qName(nullAtom(), localName, namespaceURI);
2649     synchronizeAttribute(qName);
2650     const Attribute* attribute = elementData()->findAttributeByName(qName);
2651     if (!attribute)
2652         return 0;
2653     return ensureAttr(attribute->name());
2654 }
2655
2656 bool Element::hasAttribute(const AtomicString& qualifiedName) const
2657 {
2658     if (!elementData())
2659         return false;
2660     synchronizeAttribute(qualifiedName);
2661     return elementData()->findAttributeByName(qualifiedName, shouldIgnoreAttributeCase(*this));
2662 }
2663
2664 bool Element::hasAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const
2665 {
2666     if (!elementData())
2667         return false;
2668     QualifiedName qName(nullAtom(), localName, namespaceURI);
2669     synchronizeAttribute(qName);
2670     return elementData()->findAttributeByName(qName);
2671 }
2672
2673 void Element::focus(bool restorePreviousSelection, FocusDirection direction)
2674 {
2675     if (!isConnected())
2676         return;
2677
2678     if (document().focusedElement() == this) {
2679         if (document().page())
2680             document().page()->chrome().client().elementDidRefocus(*this);
2681
2682         return;
2683     }
2684
2685     // If the stylesheets have already been loaded we can reliably check isFocusable.
2686     // If not, we continue and set the focused node on the focus controller below so
2687     // that it can be updated soon after attach. 
2688     if (document().haveStylesheetsLoaded()) {
2689         document().updateStyleIfNeeded();
2690         if (!isFocusable())
2691             return;
2692     }
2693
2694     if (!supportsFocus())
2695         return;
2696
2697     RefPtr<Node> protect;
2698     if (Page* page = document().page()) {
2699         // Focus and change event handlers can cause us to lose our last ref.
2700         // If a focus event handler changes the focus to a different node it
2701         // does not make sense to continue and update appearence.
2702         protect = this;
2703         if (!page->focusController().setFocusedElement(this, *document().frame(), direction))
2704             return;
2705     }
2706
2707     SelectionRevealMode revealMode = SelectionRevealMode::Reveal;
2708 #if PLATFORM(IOS_FAMILY)
2709     // Focusing a form element triggers animation in UIKit to scroll to the right position.
2710     // Calling updateFocusAppearance() would generate an unnecessary call to ScrollView::setScrollPosition(),
2711     // which would jump us around during this animation. See <rdar://problem/6699741>.
2712     bool isFormControl = is<HTMLFormControlElement>(*this);
2713     if (isFormControl)
2714         revealMode = SelectionRevealMode::RevealUpToMainFrame;
2715 #endif
2716
2717     auto target = focusAppearanceUpdateTarget();
2718     if (!target)
2719         return;
2720
2721     target->updateFocusAppearance(restorePreviousSelection ? SelectionRestorationMode::Restore : SelectionRestorationMode::SetDefault, revealMode);
2722 }
2723
2724 RefPtr<Element> Element::focusAppearanceUpdateTarget()
2725 {
2726     return this;
2727 }
2728
2729 void Element::updateFocusAppearance(SelectionRestorationMode, SelectionRevealMode revealMode)
2730 {
2731     if (isRootEditableElement()) {
2732         // Keep frame alive in this method, since setSelection() may release the last reference to |frame|.
2733         RefPtr<Frame> frame = document().frame();
2734         if (!frame)
2735             return;
2736         
2737         // When focusing an editable element in an iframe, don't reset the selection if it already contains a selection.
2738         if (this == frame->selection().selection().rootEditableElement())
2739             return;
2740
2741         // FIXME: We should restore the previous selection if there is one.
2742         VisibleSelection newSelection = VisibleSelection(firstPositionInOrBeforeNode(this), DOWNSTREAM);
2743         
2744         if (frame->selection().shouldChangeSelection(newSelection)) {
2745             frame->selection().setSelection(newSelection, FrameSelection::defaultSetSelectionOptions(), Element::defaultFocusTextStateChangeIntent());
2746             frame->selection().revealSelection(revealMode);
2747         }
2748     }
2749
2750     if (RefPtr<FrameView> view = document().view())
2751         view->scheduleScrollToFocusedElement(revealMode);
2752 }
2753
2754 void Element::blur()
2755 {
2756     if (treeScope().focusedElementInScope() == this) {
2757         if (Frame* frame = document().frame())
2758             frame->page()->focusController().setFocusedElement(nullptr, *frame);
2759         else
2760             document().setFocusedElement(nullptr);
2761     }
2762 }
2763
2764 void Element::dispatchFocusInEvent(const AtomicString& eventType, RefPtr<Element>&& oldFocusedElement)
2765 {
2766     ASSERT_WITH_SECURITY_IMPLICATION(ScriptDisallowedScope::InMainThread::isScriptAllowed());
2767     ASSERT(eventType == eventNames().focusinEvent || eventType == eventNames().DOMFocusInEvent);
2768     dispatchScopedEvent(FocusEvent::create(eventType, Event::CanBubble::Yes, Event::IsCancelable::No, document().windowProxy(), 0, WTFMove(oldFocusedElement)));
2769 }
2770
2771 void Element::dispatchFocusOutEvent(const AtomicString& eventType, RefPtr<Element>&& newFocusedElement)
2772 {
2773     ASSERT_WITH_SECURITY_IMPLICATION(ScriptDisallowedScope::InMainThread::isScriptAllowed());
2774     ASSERT(eventType == eventNames().focusoutEvent || eventType == eventNames().DOMFocusOutEvent);
2775     dispatchScopedEvent(FocusEvent::create(eventType, Event::CanBubble::Yes, Event::IsCancelable::No, document().windowProxy(), 0, WTFMove(newFocusedElement)));
2776 }
2777
2778 void Element::dispatchFocusEvent(RefPtr<Element>&& oldFocusedElement, FocusDirection)
2779 {
2780     if (auto* page = document().page())
2781         page->chrome().client().elementDidFocus(*this);
2782     dispatchEvent(FocusEvent::create(eventNames().focusEvent, Event::CanBubble::No, Event::IsCancelable::No, document().windowProxy(), 0, WTFMove(oldFocusedElement)));
2783 }
2784
2785 void Element::dispatchBlurEvent(RefPtr<Element>&& newFocusedElement)
2786 {
2787     if (auto* page = document().page())
2788         page->chrome().client().elementDidBlur(*this);
2789     dispatchEvent(FocusEvent::create(eventNames().blurEvent, Event::CanBubble::No, Event::IsCancelable::No, document().windowProxy(), 0, WTFMove(newFocusedElement)));
2790 }
2791
2792 void Element::dispatchWebKitImageReadyEventForTesting()
2793 {
2794     if (document().settings().webkitImageReadyEventEnabled())
2795         dispatchEvent(Event::create("webkitImageFrameReady", Event::CanBubble::Yes, Event::IsCancelable::Yes));
2796 }
2797
2798 bool Element::dispatchMouseForceWillBegin()
2799 {
2800 #if ENABLE(MOUSE_FORCE_EVENTS)
2801     if (!document().hasListenerType(Document::FORCEWILLBEGIN_LISTENER))
2802         return false;
2803
2804     Frame* frame = document().frame();
2805     if (!frame)
2806         return false;
2807
2808     PlatformMouseEvent platformMouseEvent { frame->eventHandler().lastKnownMousePosition(), frame->eventHandler().lastKnownMouseGlobalPosition(), NoButton, PlatformEvent::NoType, 1, false, false, false, false, WallTime::now(), ForceAtClick, NoTap };
2809     auto mouseForceWillBeginEvent = MouseEvent::create(eventNames().webkitmouseforcewillbeginEvent, document().windowProxy(), platformMouseEvent, 0, nullptr);
2810     mouseForceWillBeginEvent->setTarget(this);
2811     dispatchEvent(mouseForceWillBeginEvent);
2812
2813     if (mouseForceWillBeginEvent->defaultHandled() || mouseForceWillBeginEvent->defaultPrevented())
2814         return true;
2815 #endif
2816
2817     return false;
2818 }
2819
2820 ExceptionOr<void> Element::mergeWithNextTextNode(Text& node)
2821 {
2822     auto* next = node.nextSibling();
2823     if (!is<Text>(next))
2824         return { };
2825     Ref<Text> textNext { downcast<Text>(*next) };
2826     node.appendData(textNext->data());
2827     return textNext->remove();
2828 }
2829
2830 String Element::innerHTML() const
2831 {
2832     return serializeFragment(*this, SerializedNodes::SubtreesOfChildren);
2833 }
2834
2835 String Element::outerHTML() const
2836 {
2837     return serializeFragment(*this, SerializedNodes::SubtreeIncludingNode);
2838 }
2839
2840 ExceptionOr<void> Element::setOuterHTML(const String& html)
2841 {
2842     auto* parentElement = this->parentElement();
2843     if (!is<HTMLElement>(parentElement))
2844         return Exception { NoModificationAllowedError };
2845
2846     Ref<HTMLElement> parent = downcast<HTMLElement>(*parentElement);
2847     RefPtr<Node> prev = previousSibling();
2848     RefPtr<Node> next = nextSibling();
2849
2850     auto fragment = createFragmentForInnerOuterHTML(parent, html, AllowScriptingContent);
2851     if (fragment.hasException())
2852         return fragment.releaseException();
2853
2854     auto replaceResult = parent->replaceChild(fragment.releaseReturnValue().get(), *this);
2855     if (replaceResult.hasException())
2856         return replaceResult.releaseException();
2857
2858     RefPtr<Node> node = next ? next->previousSibling() : nullptr;
2859     if (is<Text>(node)) {
2860         auto result = mergeWithNextTextNode(downcast<Text>(*node));
2861         if (result.hasException())
2862             return result.releaseException();
2863     }
2864     if (is<Text>(prev)) {
2865         auto result = mergeWithNextTextNode(downcast<Text>(*prev));
2866         if (result.hasException())
2867             return result.releaseException();
2868     }
2869     return { };
2870 }
2871
2872
2873 ExceptionOr<void> Element::setInnerHTML(const String& html)
2874 {
2875     auto fragment = createFragmentForInnerOuterHTML(*this, html, AllowScriptingContent);
2876     if (fragment.hasException())
2877         return fragment.releaseException();
2878
2879     ContainerNode* container;
2880     if (!is<HTMLTemplateElement>(*this))
2881         container = this;
2882     else
2883         container = &downcast<HTMLTemplateElement>(*this).content();
2884
2885     return replaceChildrenWithFragment(*container, fragment.releaseReturnValue());
2886 }
2887
2888 String Element::innerText()
2889 {
2890     // We need to update layout, since plainText uses line boxes in the render tree.
2891     document().updateLayoutIgnorePendingStylesheets();
2892
2893     if (!renderer())
2894         return textContent(true);
2895
2896     return plainText(rangeOfContents(*this).ptr());
2897 }
2898
2899 String Element::outerText()
2900 {
2901     // Getting outerText is the same as getting innerText, only
2902     // setting is different. You would think this should get the plain
2903     // text for the outer range, but this is wrong, <br> for instance
2904     // would return different values for inner and outer text by such
2905     // a rule, but it doesn't in WinIE, and we want to match that.
2906     return innerText();
2907 }
2908
2909 String Element::title() const
2910 {
2911     return String();
2912 }
2913
2914 const AtomicString& Element::pseudo() const
2915 {
2916     return attributeWithoutSynchronization(pseudoAttr);
2917 }
2918
2919 void Element::setPseudo(const AtomicString& value)
2920 {
2921     setAttributeWithoutSynchronization(pseudoAttr, value);
2922 }
2923
2924 LayoutSize Element::minimumSizeForResizing() const
2925 {
2926     return hasRareData() ? elementRareData()->minimumSizeForResizing() : defaultMinimumSizeForResizing();
2927 }
2928
2929 void Element::setMinimumSizeForResizing(const LayoutSize& size)
2930 {
2931     if (!hasRareData() && size == defaultMinimumSizeForResizing())
2932         return;
2933     ensureElementRareData().setMinimumSizeForResizing(size);
2934 }
2935
2936 void Element::willBecomeFullscreenElement()
2937 {
2938     for (auto& child : descendantsOfType<Element>(*this))
2939         child.ancestorWillEnterFullscreen();
2940 }
2941
2942 static PseudoElement* beforeOrAfterPseudoElement(Element& host, PseudoId pseudoElementSpecifier)
2943 {
2944     switch (pseudoElementSpecifier) {
2945     case PseudoId::Before:
2946         return host.beforePseudoElement();
2947     case PseudoId::After:
2948         return host.afterPseudoElement();
2949     default:
2950         return nullptr;
2951     }
2952 }
2953
2954 const RenderStyle* Element::existingComputedStyle() const
2955 {
2956     if (hasRareData()) {
2957         if (auto* style = elementRareData()->computedStyle())
2958             return style;
2959     }
2960
2961     return renderStyle();
2962 }
2963
2964 const RenderStyle* Element::renderOrDisplayContentsStyle() const
2965 {
2966     if (auto* style = renderStyle())
2967         return style;
2968
2969     if (!hasRareData())
2970         return nullptr;
2971     auto* style = elementRareData()->computedStyle();
2972     if (style && style->display() == DisplayType::Contents)
2973         return style;
2974
2975     return nullptr;
2976 }
2977
2978 const RenderStyle& Element::resolveComputedStyle()
2979 {
2980     ASSERT(isConnected());
2981     ASSERT(!existingComputedStyle());
2982
2983     Deque<RefPtr<Element>, 32> elementsRequiringComputedStyle({ this });
2984     const RenderStyle* computedStyle = nullptr;
2985
2986     // Collect ancestors until we find one that has style.
2987     auto composedAncestors = composedTreeAncestors(*this);
2988     for (auto& ancestor : composedAncestors) {
2989         if (auto* existingStyle = ancestor.existingComputedStyle()) {
2990             computedStyle = existingStyle;
2991             break;
2992         }
2993         elementsRequiringComputedStyle.prepend(&ancestor);
2994     }
2995
2996     // Resolve and cache styles starting from the most distant ancestor.
2997     for (auto& element : elementsRequiringComputedStyle) {
2998         auto style = document().styleForElementIgnoringPendingStylesheets(*element, computedStyle);
2999         computedStyle = style.get();
3000         ElementRareData& rareData = element->ensureElementRareData();
3001         rareData.setComputedStyle(WTFMove(style));
3002     }
3003
3004     return *computedStyle;
3005 }
3006
3007 const RenderStyle& Element::resolvePseudoElementStyle(PseudoId pseudoElementSpecifier)
3008 {
3009     ASSERT(!isPseudoElement());
3010
3011     auto* parentStyle = existingComputedStyle();
3012     ASSERT(parentStyle);
3013     ASSERT(!parentStyle->getCachedPseudoStyle(pseudoElementSpecifier));
3014
3015     auto style = document().styleForElementIgnoringPendingStylesheets(*this, parentStyle, pseudoElementSpecifier);
3016     if (!style) {
3017         style = RenderStyle::createPtr();
3018         style->inheritFrom(*parentStyle);
3019         style->setStyleType(pseudoElementSpecifier);
3020     }
3021
3022     auto* computedStyle = style.get();
3023     const_cast<RenderStyle*>(parentStyle)->addCachedPseudoStyle(WTFMove(style));
3024     return *computedStyle;
3025 }
3026
3027 const RenderStyle* Element::computedStyle(PseudoId pseudoElementSpecifier)
3028 {
3029     if (!isConnected())
3030         return nullptr;
3031
3032     if (PseudoElement* pseudoElement = beforeOrAfterPseudoElement(*this, pseudoElementSpecifier))
3033         return pseudoElement->computedStyle();
3034
3035     auto* style = existingComputedStyle();
3036     if (!style)
3037         style = &resolveComputedStyle();
3038
3039     if (pseudoElementSpecifier != PseudoId::None) {
3040         if (auto* cachedPseudoStyle = style->getCachedPseudoStyle(pseudoElementSpecifier))
3041             return cachedPseudoStyle;
3042         return &resolvePseudoElementStyle(pseudoElementSpecifier);
3043     }
3044
3045     return style;
3046 }
3047
3048 bool Element::needsStyleInvalidation() const
3049 {
3050     if (!inRenderedDocument())
3051         return false;
3052     if (styleValidity() >= Style::Validity::SubtreeInvalid)
3053         return false;
3054     if (document().hasPendingFullStyleRebuild())
3055         return false;
3056
3057     return true;
3058 }
3059
3060 void Element::setStyleAffectedByEmpty()
3061 {
3062     ensureElementRareData().setStyleAffectedByEmpty(true);
3063 }
3064
3065 void Element::setStyleAffectedByFocusWithin()
3066 {
3067     ensureElementRareData().setStyleAffectedByFocusWithin(true);
3068 }
3069
3070 void Element::setStyleAffectedByActive()
3071 {
3072     ensureElementRareData().setStyleAffectedByActive(true);
3073 }
3074
3075 void Element::setChildrenAffectedByDrag()
3076 {
3077     ensureElementRareData().setChildrenAffectedByDrag(true);
3078 }
3079
3080 void Element::setChildrenAffectedByForwardPositionalRules()
3081 {
3082     ensureElementRareData().setChildrenAffectedByForwardPositionalRules(true);
3083 }
3084
3085 void Element::setDescendantsAffectedByForwardPositionalRules()
3086 {
3087     ensureElementRareData().setDescendantsAffectedByForwardPositionalRules(true);
3088 }
3089
3090 void Element::setChildrenAffectedByBackwardPositionalRules()
3091 {
3092     ensureElementRareData().setChildrenAffectedByBackwardPositionalRules(true);
3093 }
3094
3095 void Element::setDescendantsAffectedByBackwardPositionalRules()
3096 {
3097     ensureElementRareData().setDescendantsAffectedByBackwardPositionalRules(true);
3098 }
3099
3100 void Element::setChildrenAffectedByPropertyBasedBackwardPositionalRules()
3101 {
3102     ensureElementRareData().setChildrenAffectedByPropertyBasedBackwardPositionalRules(true);
3103 }
3104
3105 void Element::setChildIndex(unsigned index)
3106 {
3107     ElementRareData& rareData = ensureElementRareData();
3108     rareData.setChildIndex(index);
3109 }
3110
3111 bool Element::hasFlagsSetDuringStylingOfChildren() const
3112 {
3113     if (childrenAffectedByHover() || childrenAffectedByFirstChildRules() || childrenAffectedByLastChildRules())
3114         return true;
3115
3116     if (!hasRareData())
3117         return false;
3118     return rareDataStyleAffectedByActive()
3119         || rareDataChildrenAffectedByDrag()
3120         || rareDataChildrenAffectedByForwardPositionalRules()
3121         || rareDataDescendantsAffectedByForwardPositionalRules()
3122         || rareDataChildrenAffectedByBackwardPositionalRules()
3123         || rareDataDescendantsAffectedByBackwardPositionalRules()
3124         || rareDataChildrenAffectedByPropertyBasedBackwardPositionalRules();
3125 }
3126
3127 bool Element::rareDataStyleAffectedByEmpty() const
3128 {
3129     ASSERT(hasRareData());
3130     return elementRareData()->styleAffectedByEmpty();
3131 }
3132
3133 bool Element::rareDataStyleAffectedByFocusWithin() const
3134 {
3135     ASSERT(hasRareData());
3136     return elementRareData()->styleAffectedByFocusWithin();
3137 }
3138
3139 bool Element::rareDataStyleAffectedByActive() const
3140 {
3141     ASSERT(hasRareData());
3142     return elementRareData()->styleAffectedByActive();
3143 }
3144
3145 bool Element::rareDataChildrenAffectedByDrag() const
3146 {
3147     ASSERT(hasRareData());
3148     return elementRareData()->childrenAffectedByDrag();
3149 }
3150
3151 bool Element::rareDataChildrenAffectedByForwardPositionalRules() const
3152 {
3153     ASSERT(hasRareData());
3154     return elementRareData()->childrenAffectedByForwardPositionalRules();
3155 }
3156
3157 bool Element::rareDataDescendantsAffectedByForwardPositionalRules() const
3158 {
3159     ASSERT(hasRareData());
3160     return elementRareData()->descendantsAffectedByForwardPositionalRules();
3161 }
3162
3163 bool Element::rareDataChildrenAffectedByBackwardPositionalRules() const
3164 {
3165     ASSERT(hasRareData());
3166     return elementRareData()->childrenAffectedByBackwardPositionalRules();
3167 }
3168
3169 bool Element::rareDataDescendantsAffectedByBackwardPositionalRules() const
3170 {
3171     ASSERT(hasRareData());
3172     return elementRareData()->descendantsAffectedByBackwardPositionalRules();
3173 }
3174
3175 bool Element::rareDataChildrenAffectedByPropertyBasedBackwardPositionalRules() const
3176 {
3177     ASSERT(hasRareData());
3178     return elementRareData()->childrenAffectedByPropertyBasedBackwardPositionalRules();
3179 }
3180
3181 unsigned Element::rareDataChildIndex() const
3182 {
3183     ASSERT(hasRareData());
3184     return elementRareData()->childIndex();
3185 }
3186
3187 AtomicString Element::computeInheritedLanguage() const
3188 {
3189     if (const ElementData* elementData = this->elementData()) {
3190         if (const Attribute* attribute = elementData->findLanguageAttribute())
3191             return attribute->value();
3192     }
3193
3194     // The language property is inherited, so we iterate over the parents to find the first language.
3195     const Node* currentNode = this;
3196     while ((currentNode = currentNode->parentNode())) {
3197         if (is<Element>(*currentNode)) {
3198             if (const ElementData* elementData = downcast<Element>(*currentNode).elementData()) {
3199                 if (const Attribute* attribute = elementData->findLanguageAttribute())
3200                     return attribute->value();
3201             }
3202         } else if (is<Document>(*currentNode)) {
3203             // checking the MIME content-language
3204             return downcast<Document>(*currentNode).contentLanguage();
3205         }
3206     }
3207
3208     return nullAtom();
3209 }
3210
3211 Locale& Element::locale() const
3212 {
3213     return document().getCachedLocale(computeInheritedLanguage());
3214 }
3215
3216 void Element::normalizeAttributes()
3217 {
3218     if (!hasAttributes())
3219         return;
3220
3221     auto* attrNodeList = attrNodeListForElement(*this);
3222     if (!attrNodeList)
3223         return;
3224
3225     // Copy the Attr Vector because Node::normalize() can fire synchronous JS
3226     // events (e.g. DOMSubtreeModified) and a JS listener could add / remove
3227     // attributes while we are iterating.
3228     auto copyOfAttrNodeList = *attrNodeList;
3229     for (auto& attrNode : copyOfAttrNodeList)
3230         attrNode->normalize();
3231 }
3232
3233 PseudoElement* Element::beforePseudoElement() const
3234 {
3235     return hasRareData() ? elementRareData()->beforePseudoElement() : nullptr;
3236 }
3237
3238 PseudoElement* Element::afterPseudoElement() const
3239 {
3240     return hasRareData() ? elementRareData()->afterPseudoElement() : nullptr;
3241 }
3242
3243 void Element::setBeforePseudoElement(Ref<PseudoElement>&& element)
3244 {
3245     ensureElementRareData().setBeforePseudoElement(WTFMove(element));
3246 }
3247
3248 void Element::setAfterPseudoElement(Ref<PseudoElement>&& element)
3249 {
3250     ensureElementRareData().setAfterPseudoElement(WTFMove(element));
3251 }
3252
3253 static void disconnectPseudoElement(PseudoElement* pseudoElement)
3254 {
3255     if (!pseudoElement)
3256         return;
3257     ASSERT(!pseudoElement->renderer());
3258     ASSERT(pseudoElement->hostElement());
3259     pseudoElement->clearHostElement();
3260 }
3261
3262 void Element::clearBeforePseudoElement()
3263 {
3264     if (!hasRareData())
3265         return;
3266     disconnectPseudoElement(elementRareData()->beforePseudoElement());
3267     elementRareData()->setBeforePseudoElement(nullptr);
3268 }
3269
3270 void Element::clearAfterPseudoElement()
3271 {
3272     if (!hasRareData())
3273         return;
3274     disconnectPseudoElement(elementRareData()->afterPseudoElement());
3275     elementRareData()->setAfterPseudoElement(nullptr);
3276 }
3277
3278 bool Element::matchesValidPseudoClass() const
3279 {
3280     return false;
3281 }
3282
3283 bool Element::matchesInvalidPseudoClass() const
3284 {
3285     return false;
3286 }
3287
3288 bool Element::matchesReadWritePseudoClass() const
3289 {
3290     return false;
3291 }
3292
3293 bool Element::matchesIndeterminatePseudoClass() const
3294 {
3295     return shouldAppearIndeterminate();
3296 }
3297
3298 bool Element::matchesDefaultPseudoClass() const
3299 {
3300     return false;
3301 }
3302
3303 ExceptionOr<bool> Element::matches(const String& selector)
3304 {
3305     auto query = document().selectorQueryForString(selector);
3306     if (query.hasException())
3307         return query.releaseException();
3308     return query.releaseReturnValue().matches(*this);
3309 }
3310
3311 ExceptionOr<Element*> Element::closest(const String& selector)
3312 {
3313     auto query = document().selectorQueryForString(selector);
3314     if (query.hasException())
3315         return query.releaseException();
3316     return query.releaseReturnValue().closest(*this);
3317 }
3318
3319 bool Element::shouldAppearIndeterminate() const
3320 {
3321     return false;
3322 }
3323
3324 bool Element::mayCauseRepaintInsideViewport(const IntRect* visibleRect) const
3325 {
3326     return renderer() && renderer()->mayCauseRepaintInsideViewport(visibleRect);
3327 }
3328
3329 DOMTokenList& Element::classList()
3330 {
3331     ElementRareData& data = ensureElementRareData();
3332     if (!data.classList())
3333         data.setClassList(std::make_unique<DOMTokenList>(*this, HTMLNames::classAttr));
3334     return *data.classList();
3335 }
3336
3337 DatasetDOMStringMap& Element::dataset()
3338 {
3339     ElementRareData& data = ensureElementRareData();
3340     if (!data.dataset())
3341         data.setDataset(std::make_unique<DatasetDOMStringMap>(*this));
3342     return *data.dataset();
3343 }
3344
3345 URL Element::getURLAttribute(const QualifiedName& name) const
3346 {
3347 #if !ASSERT_DISABLED
3348     if (elementData()) {
3349         if (const Attribute* attribute = findAttributeByName(name))
3350             ASSERT(isURLAttribute(*attribute));
3351     }
3352 #endif
3353     return document().completeURL(stripLeadingAndTrailingHTMLSpaces(getAttribute(name)));
3354 }
3355
3356 URL Element::getNonEmptyURLAttribute(const QualifiedName& name) const
3357 {
3358 #if !ASSERT_DISABLED
3359     if (elementData()) {
3360         if (const Attribute* attribute = findAttributeByName(name))
3361             ASSERT(isURLAttribute(*attribute));
3362     }
3363 #endif
3364     String value = stripLeadingAndTrailingHTMLSpaces(getAttribute(name));
3365     if (value.isEmpty())
3366         return URL();
3367     return document().completeURL(value);
3368 }
3369
3370 int Element::getIntegralAttribute(const QualifiedName& attributeName) const
3371 {
3372     return parseHTMLInteger(getAttribute(attributeName)).value_or(0);
3373 }
3374
3375 void Element::setIntegralAttribute(const QualifiedName& attributeName, int value)
3376 {
3377     setAttribute(attributeName, AtomicString::number(value));
3378 }
3379
3380 unsigned Element::getUnsignedIntegralAttribute(const QualifiedName& attributeName) const
3381 {
3382     return parseHTMLNonNegativeInteger(getAttribute(attributeName)).value_or(0);
3383 }
3384
3385 void Element::setUnsignedIntegralAttribute(const QualifiedName& attributeName, unsigned value)
3386 {
3387     setAttribute(attributeName, AtomicString::number(limitToOnlyHTMLNonNegative(value)));
3388 }
3389
3390 bool Element::childShouldCreateRenderer(const Node& child) const
3391 {
3392     // Only create renderers for SVG elements whose parents are SVG elements, or for proper <svg xmlns="svgNS"> subdocuments.
3393     if (child.isSVGElement()) {
3394         ASSERT(!isSVGElement());
3395         const SVGElement& childElement = downcast<SVGElement>(child);
3396         return is<SVGSVGElement>(childElement) && childElement.isValid();
3397     }
3398     return true;
3399 }
3400
3401 #if ENABLE(FULLSCREEN_API)
3402 void Element::webkitRequestFullscreen()
3403 {
3404     document().requestFullScreenForElement(this, Document::EnforceIFrameAllowFullScreenRequirement);
3405 }
3406
3407 bool Element::containsFullScreenElement() const
3408 {
3409     return hasRareData() && elementRareData()->containsFullScreenElement();
3410 }
3411
3412 void Element::setContainsFullScreenElement(bool flag)
3413 {
3414     ensureElementRareData().setContainsFullScreenElement(flag);
3415     invalidateStyleAndLayerComposition();
3416 }
3417
3418 static Element* parentCrossingFrameBoundaries(Element* element)
3419 {
3420     ASSERT(element);
3421     return element->parentElement() ? element->parentElement() : element->document().ownerElement();
3422 }
3423
3424 void Element::setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(bool flag)
3425 {
3426     Element* element = this;
3427     while ((element = parentCrossingFrameBoundaries(element)))
3428         element->setContainsFullScreenElement(flag);
3429 }
3430 #endif
3431
3432 #if ENABLE(POINTER_LOCK)
3433 void Element::requestPointerLock()
3434 {
3435     if (document().page())
3436         document().page()->pointerLockController().requestPointerLock(this);
3437 }
3438 #endif
3439
3440 #if ENABLE(INTERSECTION_OBSERVER)
3441 void Element::disconnectFromIntersectionObservers()
3442 {
3443     auto* observerData = intersectionObserverData();
3444     if (!observerData)
3445         return;
3446
3447     for (const auto& registration : observerData->registrations)
3448         registration.observer->targetDestroyed(*this);
3449     observerData->registrations.clear();
3450
3451     for (const auto& observer : observerData->observers)
3452         observer->rootDestroyed();
3453     observerData->observers.clear();
3454 }
3455
3456 IntersectionObserverData& Element::ensureIntersectionObserverData()
3457 {
3458     auto& rareData = ensureElementRareData();
3459     if (!rareData.intersectionObserverData())
3460         rareData.setIntersectionObserverData(std::make_unique<IntersectionObserverData>());
3461     return *rareData.intersectionObserverData();
3462 }
3463
3464 IntersectionObserverData* Element::intersectionObserverData()
3465 {
3466     return hasRareData() ? elementRareData()->intersectionObserverData() : nullptr;
3467 }
3468 #endif
3469
3470 SpellcheckAttributeState Element::spellcheckAttributeState() const
3471 {
3472     const AtomicString& value = attributeWithoutSynchronization(HTMLNames::spellcheckAttr);
3473     if (value.isNull())
3474         return SpellcheckAttributeDefault;
3475     if (value.isEmpty() || equalLettersIgnoringASCIICase(value, "true"))
3476         return SpellcheckAttributeTrue;
3477     if (equalLettersIgnoringASCIICase(value, "false"))
3478         return SpellcheckAttributeFalse;
3479     return SpellcheckAttributeDefault;
3480 }
3481
3482 bool Element::isSpellCheckingEnabled() const
3483 {
3484     for (const Element* element = this; element; element = element->parentOrShadowHostElement()) {
3485         switch (element->spellcheckAttributeState()) {
3486         case SpellcheckAttributeTrue:
3487             return true;
3488         case SpellcheckAttributeFalse:
3489             return false;
3490         case SpellcheckAttributeDefault:
3491             break;
3492         }
3493     }
3494
3495     return true;
3496 }
3497
3498 #ifndef NDEBUG
3499 bool Element::fastAttributeLookupAllowed(const QualifiedName& name) const
3500 {
3501     if (name == HTMLNames::styleAttr)
3502         return false;
3503
3504     if (isSVGElement())
3505         return !downcast<SVGElement>(*this).isAnimatableAttribute(name);
3506
3507     return true;
3508 }
3509 #endif
3510
3511 #if DUMP_NODE_STATISTICS
3512 bool Element::hasNamedNodeMap() const
3513 {
3514     return hasRareData() && elementRareData()->attributeMap();
3515 }
3516 #endif
3517
3518 inline void Element::updateName(const AtomicString& oldName, const AtomicString& newName)
3519 {
3520     if (!isInTreeScope())
3521         return;
3522
3523     if (oldName == newName)
3524         return;
3525
3526     updateNameForTreeScope(treeScope(), oldName, newName);
3527
3528     if (!isConnected())
3529         return;
3530     if (!is<HTMLDocument>(document()))
3531         return;
3532     updateNameForDocument(downcast<HTMLDocument>(document()), oldName, newName);
3533 }
3534
3535 void Element::updateNameForTreeScope(TreeScope& scope, const AtomicString& oldName, const AtomicString& newName)
3536 {
3537     ASSERT(oldName != newName);
3538
3539     if (!oldName.isEmpty())
3540         scope.removeElementByName(*oldName.impl(), *this);
3541     if (!newName.isEmpty())
3542         scope.addElementByName(*newName.impl(), *this);
3543 }
3544
3545 void Element::updateNameForDocument(HTMLDocument& document, const AtomicString& oldName, const AtomicString& newName)
3546 {
3547     ASSERT(oldName != newName);
3548
3549     if (isInShadowTree())
3550         return;
3551
3552     if (WindowNameCollection::elementMatchesIfNameAttributeMatch(*this)) {
3553         const AtomicString& id = WindowNameCollection::elementMatchesIfIdAttributeMatch(*this) ? getIdAttribute() : nullAtom();
3554         if (!oldName.isEmpty() && oldName != id)
3555             document.removeWindowNamedItem(*oldName.impl(), *this);
3556         if (!newName.isEmpty() && newName != id)
3557             document.addWindowNamedItem(*newName.impl(), *this);
3558     }
3559
3560     if (DocumentNameCollection::elementMatchesIfNameAttributeMatch(*this)) {
3561         const AtomicString& id = DocumentNameCollection::elementMatchesIfIdAttributeMatch(*this) ? getIdAttribute() : nullAtom();
3562         if (!oldName.isEmpty() && oldName != id)
3563             document.removeDocumentNamedItem(*oldName.impl(), *this);
3564         if (!newName.isEmpty() && newName != id)
3565             document.addDocumentNamedItem(*newName.impl(), *this);
3566     }
3567 }
3568
3569 inline void Element::updateId(const AtomicString& oldId, const AtomicString& newId, NotifyObservers notifyObservers)
3570 {
3571     if (!isInTreeScope())
3572         return;
3573
3574     if (oldId == newId)
3575         return;
3576
3577     updateIdForTreeScope(treeScope(), oldId, newId, notifyObservers);
3578
3579     if (!isConnected())
3580         return;
3581     if (!is<HTMLDocument>(document()))
3582         return;
3583     updateIdForDocument(downcast<HTMLDocument>(document()), oldId, newId, UpdateHTMLDocumentNamedItemMapsOnlyIfDiffersFromNameAttribute);
3584 }
3585
3586 void Element::updateIdForTreeScope(TreeScope& scope, const AtomicString& oldId, const AtomicString& newId, NotifyObservers notifyObservers)
3587 {
3588     ASSERT(isInTreeScope());
3589     ASSERT(oldId != newId);
3590
3591     if (!oldId.isEmpty())
3592         scope.removeElementById(*oldId.impl(), *this, notifyObservers == NotifyObservers::Yes);
3593     if (!newId.isEmpty())
3594         scope.addElementById(*newId.impl(), *this, notifyObservers == NotifyObservers::Yes);
3595 }
3596
3597 void Element::updateIdForDocument(HTMLDocument& document, const AtomicString& oldId, const AtomicString& newId, HTMLDocumentNamedItemMapsUpdatingCondition condition)
3598 {
3599     ASSERT(isConnected());
3600     ASSERT(oldId != newId);
3601
3602     if (isInShadowTree())
3603         return;
3604
3605     if (WindowNameCollection::elementMatchesIfIdAttributeMatch(*this)) {
3606         const AtomicString& name = condition == UpdateHTMLDocumentNamedItemMapsOnlyIfDiffersFromNameAttribute && WindowNameCollection::elementMatchesIfNameAttributeMatch(*this) ? getNameAttribute() : nullAtom();
3607         if (!oldId.isEmpty() && oldId != name)
3608             document.removeWindowNamedItem(*oldId.impl(), *this);
3609         if (!newId.isEmpty() && newId != name)
3610             document.addWindowNamedItem(*newId.impl(), *this);
3611     }
3612
3613     if (DocumentNameCollection::elementMatchesIfIdAttributeMatch(*this)) {
3614         const AtomicString& name = condition == UpdateHTMLDocumentNamedItemMapsOnlyIfDiffersFromNameAttribute && DocumentNameCollection::elementMatchesIfNameAttributeMatch(*this) ? getNameAttribute() : nullAtom();
3615         if (!oldId.isEmpty() && oldId != name)
3616             document.removeDocumentNamedItem(*oldId.impl(), *this);
3617         if (!newId.isEmpty() && newId != name)
3618             document.addDocumentNamedItem(*newId.impl(), *this);
3619     }
3620 }
3621
3622 void Element::updateLabel(TreeScope& scope, const AtomicString& oldForAttributeValue, const AtomicString& newForAttributeValue)
3623 {
3624     ASSERT(hasTagName(labelTag));
3625
3626     if (!isConnected())
3627         return;
3628
3629     if (oldForAttributeValue == newForAttributeValue)
3630         return;
3631
3632     if (!oldForAttributeValue.isEmpty())
3633         scope.removeLabel(*oldForAttributeValue.impl(), downcast<HTMLLabelElement>(*this));
3634     if (!newForAttributeValue.isEmpty())
3635         scope.addLabel(*newForAttributeValue.impl(), downcast<HTMLLabelElement>(*this));
3636 }
3637
3638 void Element::willModifyAttribute(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue)
3639 {
3640     if (name == HTMLNames::idAttr)
3641         updateId(oldValue, newValue, NotifyObservers::No); // Will notify observers after the attribute is actually changed.
3642     else if (name == HTMLNames::nameAttr)
3643         updateName(oldValue, newValue);
3644     else if (name == HTMLNames::forAttr && hasTagName(labelTag)) {
3645         if (treeScope().shouldCacheLabelsByForAttribute())
3646             updateLabel(treeScope(), oldValue, newValue);
3647     }
3648
3649     if (auto recipients = MutationObserverInterestGroup::createForAttributesMutation(*this, name))
3650         recipients->enqueueMutationRecord(MutationRecord::createAttributes(*this, name, oldValue));
3651
3652     InspectorInstrumentation::willModifyDOMAttr(document(), *this, oldValue, newValue);
3653 }
3654
3655 void Element::didAddAttribute(const QualifiedName& name, const AtomicString& value)
3656 {
3657     attributeChanged(name, nullAtom(), value);
3658     InspectorInstrumentation::didModifyDOMAttr(document(), *this, name.localName(), value);
3659     dispatchSubtreeModifiedEvent();
3660 }
3661
3662 void Element::didModifyAttribute(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue)
3663 {
3664     attributeChanged(name, oldValue, newValue);
3665     InspectorInstrumentation::didModifyDOMAttr(document(), *this, name.localName(), newValue);
3666     // Do not dispatch a DOMSubtreeModified event here; see bug 81141.
3667 }
3668
3669 void Element::didRemoveAttribute(const QualifiedName& name, const AtomicString& oldValue)
3670 {
3671     attributeChanged(name, oldValue, nullAtom());
3672     InspectorInstrumentation::didRemoveDOMAttr(document(), *this, name.localName());
3673     dispatchSubtreeModifiedEvent();
3674 }