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