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