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