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