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