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