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