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