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