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, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
8 * (C) 2007 Eric Seidel (eric@webkit.org)
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.
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.
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.
29 #include "AXObjectCache.h"
31 #include "CSSParser.h"
32 #include "CSSSelectorList.h"
33 #include "ClassList.h"
34 #include "ClientRect.h"
35 #include "ClientRectList.h"
36 #include "DOMTokenList.h"
37 #include "DatasetDOMStringMap.h"
39 #include "DocumentFragment.h"
40 #include "ElementRareData.h"
41 #include "ExceptionCode.h"
42 #include "FlowThreadController.h"
43 #include "FocusController.h"
45 #include "FrameView.h"
46 #include "HTMLCollection.h"
47 #include "HTMLDocument.h"
48 #include "HTMLElement.h"
49 #include "HTMLFormCollection.h"
50 #include "HTMLFrameOwnerElement.h"
51 #include "HTMLNames.h"
52 #include "HTMLOptionsCollection.h"
53 #include "HTMLParserIdioms.h"
54 #include "HTMLTableRowsCollection.h"
55 #include "InspectorInstrumentation.h"
56 #include "MutationObserverInterestGroup.h"
57 #include "MutationRecord.h"
58 #include "NamedNodeMap.h"
60 #include "NodeRenderStyle.h"
61 #include "NodeRenderingContext.h"
63 #include "PointerLockController.h"
64 #include "RenderRegion.h"
65 #include "RenderView.h"
66 #include "RenderWidget.h"
67 #include "SelectorQuery.h"
69 #include "ShadowRoot.h"
70 #include "StyleResolver.h"
72 #include "TextIterator.h"
73 #include "VoidCallback.h"
74 #include "WebKitAnimationList.h"
75 #include "XMLNSNames.h"
77 #include "htmlediting.h"
78 #include <wtf/text/CString.h>
81 #include "SVGElement.h"
87 using namespace HTMLNames;
88 using namespace XMLNames;
90 class StyleResolverParentPusher {
92 StyleResolverParentPusher(Element* parent)
94 , m_pushedStyleResolver(0)
99 if (m_pushedStyleResolver)
101 m_pushedStyleResolver = m_parent->document()->styleResolver();
102 m_pushedStyleResolver->pushParentElement(m_parent);
104 ~StyleResolverParentPusher()
107 if (!m_pushedStyleResolver)
110 // This tells us that our pushed style selector is in a bad state,
111 // so we should just bail out in that scenario.
112 ASSERT(m_pushedStyleResolver == m_parent->document()->styleResolver());
113 if (m_pushedStyleResolver != m_parent->document()->styleResolver())
116 m_pushedStyleResolver->popParentElement(m_parent);
121 StyleResolver* m_pushedStyleResolver;
124 PassRefPtr<Element> Element::create(const QualifiedName& tagName, Document* document)
126 return adoptRef(new Element(tagName, document, CreateElement));
132 if (document() && document()->renderer()) {
133 // When the document is not destroyed, an element that was part of a named flow
134 // content nodes should have been removed from the content nodes collection
135 // and the inNamedFlow flag reset.
136 ASSERT(!inNamedFlow());
140 if (ElementShadow* elementShadow = shadow()) {
141 elementShadow->removeAllShadowRoots();
142 elementRareData()->m_shadow.clear();
146 ASSERT(m_attributeData);
147 m_attributeData->detachAttrObjectsFromElement(this);
151 inline ElementRareData* Element::elementRareData() const
153 ASSERT(hasRareData());
154 return static_cast<ElementRareData*>(NodeRareData::rareDataFromMap(this));
157 inline ElementRareData* Element::ensureElementRareData()
159 return static_cast<ElementRareData*>(ensureRareData());
162 OwnPtr<NodeRareData> Element::createRareData()
164 return adoptPtr(new ElementRareData);
167 DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(Element, blur);
168 DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(Element, error);
169 DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(Element, focus);
170 DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(Element, load);
172 PassRefPtr<Node> Element::cloneNode(bool deep)
174 return deep ? cloneElementWithChildren() : cloneElementWithoutChildren();
177 PassRefPtr<Element> Element::cloneElementWithChildren()
179 RefPtr<Element> clone = cloneElementWithoutChildren();
180 cloneChildNodes(clone.get());
181 return clone.release();
184 PassRefPtr<Element> Element::cloneElementWithoutChildren()
186 RefPtr<Element> clone = cloneElementWithoutAttributesAndChildren();
187 // This will catch HTML elements in the wrong namespace that are not correctly copied.
188 // This is a sanity check as HTML overloads some of the DOM methods.
189 ASSERT(isHTMLElement() == clone->isHTMLElement());
191 clone->cloneDataFromElement(*this);
192 return clone.release();
195 PassRefPtr<Element> Element::cloneElementWithoutAttributesAndChildren()
197 return document()->createElement(tagQName(), false);
200 PassRefPtr<Attr> Element::detachAttribute(size_t index)
202 ASSERT(attributeData());
204 Attribute* attribute = attributeData()->attributeItem(index);
207 RefPtr<Attr> attr = attrIfExists(attribute->name());
209 attr->detachFromElementWithValue(attribute->value());
211 attr = Attr::create(document(), attribute->name(), attribute->value());
213 attributeData()->removeAttribute(index, this);
214 return attr.release();
217 void Element::removeAttribute(const QualifiedName& name)
219 if (!attributeData())
222 if (RefPtr<Attr> attr = attrIfExists(name))
223 attr->detachFromElementWithValue(attr->value());
225 attributeData()->removeAttribute(name, this);
228 void Element::setBooleanAttribute(const QualifiedName& name, bool value)
231 setAttribute(name, emptyAtom);
233 removeAttribute(name);
236 NamedNodeMap* Element::attributes() const
238 ensureUpdatedAttributeData();
239 ElementRareData* rareData = const_cast<Element*>(this)->ensureElementRareData();
240 if (NamedNodeMap* attributeMap = rareData->m_attributeMap.get())
243 rareData->m_attributeMap = NamedNodeMap::create(const_cast<Element*>(this));
244 return rareData->m_attributeMap.get();
247 Node::NodeType Element::nodeType() const
252 bool Element::hasAttribute(const QualifiedName& name) const
254 return hasAttributeNS(name.namespaceURI(), name.localName());
257 const AtomicString& Element::getAttribute(const QualifiedName& name) const
259 if (UNLIKELY(name == styleAttr) && !isStyleAttributeValid())
260 updateStyleAttribute();
263 if (UNLIKELY(!areSVGAttributesValid()))
264 updateAnimatedSVGAttribute(name);
267 if (m_attributeData) {
268 if (Attribute* attribute = getAttributeItem(name))
269 return attribute->value();
274 void Element::scrollIntoView(bool alignToTop)
276 document()->updateLayoutIgnorePendingStylesheets();
281 LayoutRect bounds = getRect();
282 // Align to the top / bottom and to the closest edge.
284 renderer()->scrollRectToVisible(bounds, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
286 renderer()->scrollRectToVisible(bounds, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignBottomAlways);
289 void Element::scrollIntoViewIfNeeded(bool centerIfNeeded)
291 document()->updateLayoutIgnorePendingStylesheets();
296 LayoutRect bounds = getRect();
298 renderer()->scrollRectToVisible(bounds, ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeeded);
300 renderer()->scrollRectToVisible(bounds, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
303 void Element::scrollByUnits(int units, ScrollGranularity granularity)
305 document()->updateLayoutIgnorePendingStylesheets();
310 if (!renderer()->hasOverflowClip())
313 ScrollDirection direction = ScrollDown;
315 direction = ScrollUp;
318 Node* stopNode = this;
319 toRenderBox(renderer())->scroll(direction, granularity, units, &stopNode);
322 void Element::scrollByLines(int lines)
324 scrollByUnits(lines, ScrollByLine);
327 void Element::scrollByPages(int pages)
329 scrollByUnits(pages, ScrollByPage);
332 static float localZoomForRenderer(RenderObject* renderer)
334 // FIXME: This does the wrong thing if two opposing zooms are in effect and canceled each
335 // other out, but the alternative is that we'd have to crawl up the whole render tree every
336 // time (or store an additional bit in the RenderStyle to indicate that a zoom was specified).
337 float zoomFactor = 1;
338 if (renderer->style()->effectiveZoom() != 1) {
339 // Need to find the nearest enclosing RenderObject that set up
340 // a differing zoom, and then we divide our result by it to eliminate the zoom.
341 RenderObject* prev = renderer;
342 for (RenderObject* curr = prev->parent(); curr; curr = curr->parent()) {
343 if (curr->style()->effectiveZoom() != prev->style()->effectiveZoom()) {
344 zoomFactor = prev->style()->zoom();
349 if (prev->isRenderView())
350 zoomFactor = prev->style()->zoom();
355 static int adjustForLocalZoom(LayoutUnit value, RenderObject* renderer)
357 float zoomFactor = localZoomForRenderer(renderer);
360 #if ENABLE(SUBPIXEL_LAYOUT)
361 return lroundf(value / zoomFactor);
363 // Needed because computeLengthInt truncates (rather than rounds) when scaling up.
366 return static_cast<int>(value / zoomFactor);
370 int Element::offsetLeft()
372 document()->updateLayoutIgnorePendingStylesheets();
373 if (RenderBoxModelObject* renderer = renderBoxModelObject())
374 return adjustForLocalZoom(renderer->pixelSnappedOffsetLeft(), renderer);
378 int Element::offsetTop()
380 document()->updateLayoutIgnorePendingStylesheets();
381 if (RenderBoxModelObject* renderer = renderBoxModelObject())
382 return adjustForLocalZoom(renderer->pixelSnappedOffsetTop(), renderer);
386 int Element::offsetWidth()
388 document()->updateLayoutIgnorePendingStylesheets();
389 if (RenderBoxModelObject* renderer = renderBoxModelObject())
390 return adjustForAbsoluteZoom(renderer->pixelSnappedOffsetWidth(), renderer);
394 int Element::offsetHeight()
396 document()->updateLayoutIgnorePendingStylesheets();
397 if (RenderBoxModelObject* renderer = renderBoxModelObject())
398 return adjustForAbsoluteZoom(renderer->pixelSnappedOffsetHeight(), renderer);
402 Element* Element::offsetParent()
404 document()->updateLayoutIgnorePendingStylesheets();
405 if (RenderObject* rend = renderer())
406 if (RenderObject* offsetParent = rend->offsetParent())
407 return static_cast<Element*>(offsetParent->node());
411 int Element::clientLeft()
413 document()->updateLayoutIgnorePendingStylesheets();
415 if (RenderBox* renderer = renderBox())
416 return adjustForAbsoluteZoom(roundToInt(renderer->clientLeft()), renderer);
420 int Element::clientTop()
422 document()->updateLayoutIgnorePendingStylesheets();
424 if (RenderBox* renderer = renderBox())
425 return adjustForAbsoluteZoom(roundToInt(renderer->clientTop()), renderer);
429 int Element::clientWidth()
431 document()->updateLayoutIgnorePendingStylesheets();
433 // When in strict mode, clientWidth for the document element should return the width of the containing frame.
434 // When in quirks mode, clientWidth for the body element should return the width of the containing frame.
435 bool inQuirksMode = document()->inQuirksMode();
436 if ((!inQuirksMode && document()->documentElement() == this) ||
437 (inQuirksMode && isHTMLElement() && document()->body() == this)) {
438 if (FrameView* view = document()->view()) {
439 if (RenderView* renderView = document()->renderView())
440 return adjustForAbsoluteZoom(view->layoutWidth(), renderView);
444 if (RenderBox* renderer = renderBox())
445 return adjustForAbsoluteZoom(renderer->pixelSnappedClientWidth(), renderer);
449 int Element::clientHeight()
451 document()->updateLayoutIgnorePendingStylesheets();
453 // When in strict mode, clientHeight for the document element should return the height of the containing frame.
454 // When in quirks mode, clientHeight for the body element should return the height of the containing frame.
455 bool inQuirksMode = document()->inQuirksMode();
457 if ((!inQuirksMode && document()->documentElement() == this) ||
458 (inQuirksMode && isHTMLElement() && document()->body() == this)) {
459 if (FrameView* view = document()->view()) {
460 if (RenderView* renderView = document()->renderView())
461 return adjustForAbsoluteZoom(view->layoutHeight(), renderView);
465 if (RenderBox* renderer = renderBox())
466 return adjustForAbsoluteZoom(renderer->pixelSnappedClientHeight(), renderer);
470 int Element::scrollLeft()
472 document()->updateLayoutIgnorePendingStylesheets();
473 if (RenderBox* rend = renderBox())
474 return adjustForAbsoluteZoom(rend->scrollLeft(), rend);
478 int Element::scrollTop()
480 document()->updateLayoutIgnorePendingStylesheets();
481 if (RenderBox* rend = renderBox())
482 return adjustForAbsoluteZoom(rend->scrollTop(), rend);
486 void Element::setScrollLeft(int newLeft)
488 document()->updateLayoutIgnorePendingStylesheets();
489 if (RenderBox* rend = renderBox())
490 rend->setScrollLeft(static_cast<int>(newLeft * rend->style()->effectiveZoom()));
493 void Element::setScrollTop(int newTop)
495 document()->updateLayoutIgnorePendingStylesheets();
496 if (RenderBox* rend = renderBox())
497 rend->setScrollTop(static_cast<int>(newTop * rend->style()->effectiveZoom()));
500 int Element::scrollWidth()
502 document()->updateLayoutIgnorePendingStylesheets();
503 if (RenderBox* rend = renderBox())
504 return adjustForAbsoluteZoom(rend->scrollWidth(), rend);
508 int Element::scrollHeight()
510 document()->updateLayoutIgnorePendingStylesheets();
511 if (RenderBox* rend = renderBox())
512 return adjustForAbsoluteZoom(rend->scrollHeight(), rend);
516 IntRect Element::boundsInRootViewSpace()
518 document()->updateLayoutIgnorePendingStylesheets();
520 FrameView* view = document()->view();
524 Vector<FloatQuad> quads;
526 if (isSVGElement() && renderer()) {
527 // Get the bounding rectangle from the SVG model.
528 SVGElement* svgElement = static_cast<SVGElement*>(this);
530 if (svgElement->boundingBox(localRect))
531 quads.append(renderer()->localToAbsoluteQuad(localRect));
535 // Get the bounding rectangle from the box model.
536 if (renderBoxModelObject())
537 renderBoxModelObject()->absoluteQuads(quads);
543 IntRect result = quads[0].enclosingBoundingBox();
544 for (size_t i = 1; i < quads.size(); ++i)
545 result.unite(quads[i].enclosingBoundingBox());
547 result = view->contentsToRootView(result);
551 PassRefPtr<ClientRectList> Element::getClientRects()
553 document()->updateLayoutIgnorePendingStylesheets();
555 RenderBoxModelObject* renderBoxModelObject = this->renderBoxModelObject();
556 if (!renderBoxModelObject)
557 return ClientRectList::create();
559 // FIXME: Handle SVG elements.
560 // FIXME: Handle table/inline-table with a caption.
562 Vector<FloatQuad> quads;
563 renderBoxModelObject->absoluteQuads(quads);
564 document()->adjustFloatQuadsForScrollAndAbsoluteZoomAndFrameScale(quads, renderBoxModelObject);
565 return ClientRectList::create(quads);
568 PassRefPtr<ClientRect> Element::getBoundingClientRect()
570 document()->updateLayoutIgnorePendingStylesheets();
572 Vector<FloatQuad> quads;
574 if (isSVGElement() && renderer() && !renderer()->isSVGRoot()) {
575 // Get the bounding rectangle from the SVG model.
576 SVGElement* svgElement = static_cast<SVGElement*>(this);
578 if (svgElement->boundingBox(localRect))
579 quads.append(renderer()->localToAbsoluteQuad(localRect));
583 // Get the bounding rectangle from the box model.
584 if (renderBoxModelObject())
585 renderBoxModelObject()->absoluteQuads(quads);
589 return ClientRect::create();
591 FloatRect result = quads[0].boundingBox();
592 for (size_t i = 1; i < quads.size(); ++i)
593 result.unite(quads[i].boundingBox());
595 document()->adjustFloatRectForScrollAndAbsoluteZoomAndFrameScale(result, renderer());
596 return ClientRect::create(result);
599 IntRect Element::screenRect() const
603 // FIXME: this should probably respect transforms
604 return renderer()->view()->frameView()->contentsToScreen(renderer()->absoluteBoundingBoxRectIgnoringTransforms());
607 static inline bool shouldIgnoreAttributeCase(const Element* e)
609 return e && e->document()->isHTMLDocument() && e->isHTMLElement();
612 const AtomicString& Element::getAttribute(const AtomicString& name) const
614 bool ignoreCase = shouldIgnoreAttributeCase(this);
616 // Update the 'style' attribute if it's invalid and being requested:
617 if (!isStyleAttributeValid() && equalPossiblyIgnoringCase(name, styleAttr.localName(), ignoreCase))
618 updateStyleAttribute();
621 if (!areSVGAttributesValid()) {
622 // We're not passing a namespace argument on purpose. SVGNames::*Attr are defined w/o namespaces as well.
623 updateAnimatedSVGAttribute(QualifiedName(nullAtom, name, nullAtom));
627 if (m_attributeData) {
628 if (Attribute* attribute = m_attributeData->getAttributeItem(name, ignoreCase))
629 return attribute->value();
635 const AtomicString& Element::getAttributeNS(const String& namespaceURI, const String& localName) const
637 return getAttribute(QualifiedName(nullAtom, localName, namespaceURI));
640 void Element::setAttribute(const AtomicString& name, const AtomicString& value, ExceptionCode& ec)
642 if (!Document::isValidName(name)) {
643 ec = INVALID_CHARACTER_ERR;
647 const AtomicString& localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
649 size_t index = ensureUpdatedAttributeData()->getAttributeItemIndex(localName, false);
650 const QualifiedName& qName = index != notFound ? attributeItem(index)->name() : QualifiedName(nullAtom, localName, nullAtom);
651 setAttributeInternal(index, qName, value, NotInUpdateStyleAttribute);
654 void Element::setAttribute(const QualifiedName& name, const AtomicString& value, EInUpdateStyleAttribute inUpdateStyleAttribute)
656 setAttributeInternal(ensureUpdatedAttributeData()->getAttributeItemIndex(name), name, value, inUpdateStyleAttribute);
659 inline void Element::setAttributeInternal(size_t index, const QualifiedName& name, const AtomicString& value, EInUpdateStyleAttribute inUpdateStyleAttribute)
661 Attribute* old = index != notFound ? m_attributeData->attributeItem(index) : 0;
662 if (value.isNull()) {
664 m_attributeData->removeAttribute(index, this, inUpdateStyleAttribute);
669 m_attributeData->addAttribute(Attribute(name, value), this, inUpdateStyleAttribute);
673 if (inUpdateStyleAttribute == NotInUpdateStyleAttribute)
674 willModifyAttribute(name, old->value(), value);
676 if (RefPtr<Attr> attrNode = attrIfExists(name))
677 attrNode->setValue(value);
679 old->setValue(value);
681 if (inUpdateStyleAttribute == NotInUpdateStyleAttribute)
682 didModifyAttribute(Attribute(old->name(), old->value()));
685 void Element::attributeChanged(const Attribute& attribute)
687 document()->incDOMTreeVersion();
689 if (isIdAttributeName(attribute.name())) {
690 if (attribute.value() != attributeData()->idForStyleResolution()) {
691 if (attribute.isNull())
692 attributeData()->setIdForStyleResolution(nullAtom);
693 else if (document()->inQuirksMode())
694 attributeData()->setIdForStyleResolution(attribute.value().lower());
696 attributeData()->setIdForStyleResolution(attribute.value());
697 setNeedsStyleRecalc();
699 } else if (attribute.name() == HTMLNames::nameAttr)
700 setHasName(!attribute.isNull());
702 if (!needsStyleRecalc() && document()->attached()) {
703 StyleResolver* styleResolver = document()->styleResolverIfExists();
704 if (!styleResolver || styleResolver->hasSelectorForAttribute(attribute.name().localName()))
705 setNeedsStyleRecalc();
708 invalidateNodeListsCacheAfterAttributeChanged(attribute.name(), this);
710 if (!AXObjectCache::accessibilityEnabled())
713 const QualifiedName& attrName = attribute.name();
714 if (attrName == aria_activedescendantAttr) {
715 // any change to aria-activedescendant attribute triggers accessibility focus change, but document focus remains intact
716 document()->axObjectCache()->handleActiveDescendantChanged(renderer());
717 } else if (attrName == roleAttr) {
718 // the role attribute can change at any time, and the AccessibilityObject must pick up these changes
719 document()->axObjectCache()->handleAriaRoleChanged(renderer());
720 } else if (attrName == aria_valuenowAttr) {
721 // If the valuenow attribute changes, AX clients need to be notified.
722 document()->axObjectCache()->postNotification(renderer(), AXObjectCache::AXValueChanged, true);
723 } else if (attrName == aria_labelAttr || attrName == aria_labeledbyAttr || attrName == altAttr || attrName == titleAttr) {
724 // If the content of an element changes due to an attribute change, notify accessibility.
725 document()->axObjectCache()->contentChanged(renderer());
726 } else if (attrName == aria_checkedAttr)
727 document()->axObjectCache()->checkedStateChanged(renderer());
728 else if (attrName == aria_selectedAttr)
729 document()->axObjectCache()->selectedChildrenChanged(renderer());
730 else if (attrName == aria_expandedAttr)
731 document()->axObjectCache()->handleAriaExpandedChange(renderer());
732 else if (attrName == aria_hiddenAttr)
733 document()->axObjectCache()->childrenChanged(renderer());
734 else if (attrName == aria_invalidAttr)
735 document()->axObjectCache()->postNotification(renderer(), AXObjectCache::AXInvalidStatusChanged, true);
738 // Returns true is the given attribute is an event handler.
739 // We consider an event handler any attribute that begins with "on".
740 // It is a simple solution that has the advantage of not requiring any
741 // code or configuration change if a new event handler is defined.
743 static bool isEventHandlerAttribute(const QualifiedName& name)
745 return name.namespaceURI().isNull() && name.localName().startsWith("on");
748 static bool isAttributeToRemove(const QualifiedName& name, const AtomicString& value)
750 return (name.localName().endsWith(hrefAttr.localName()) || name == srcAttr || name == actionAttr) && protocolIsJavaScript(stripLeadingAndTrailingHTMLSpaces(value));
753 void Element::parserSetAttributes(const Vector<Attribute>& attributeVector, FragmentScriptingPermission scriptingPermission)
755 ASSERT(!inDocument());
756 ASSERT(!parentNode());
758 ASSERT(!m_attributeData);
760 if (attributeVector.isEmpty())
763 createAttributeData();
764 m_attributeData->m_attributes = attributeVector;
765 m_attributeData->m_attributes.shrinkToFit();
767 // If the element is created as result of a paste or drag-n-drop operation
768 // we want to remove all the script and event handlers.
769 if (scriptingPermission == DisallowScriptingContent) {
771 while (i < m_attributeData->length()) {
772 const QualifiedName& attributeName = m_attributeData->m_attributes[i].name();
773 if (isEventHandlerAttribute(attributeName)) {
774 m_attributeData->m_attributes.remove(i);
778 if (isAttributeToRemove(attributeName, m_attributeData->m_attributes[i].value()))
779 m_attributeData->m_attributes[i].setValue(nullAtom);
784 // Store the set of attributes that changed on the stack in case
785 // attributeChanged mutates m_attributeData.
786 Vector<Attribute> clonedAttributes = m_attributeData->clonedAttributeVector();
787 for (unsigned i = 0; i < clonedAttributes.size(); ++i)
788 attributeChanged(clonedAttributes[i]);
791 bool Element::hasAttributes() const
793 updateInvalidAttributes();
794 return m_attributeData && m_attributeData->length();
797 bool Element::hasEquivalentAttributes(const Element* other) const
799 ElementAttributeData* attributeData = updatedAttributeData();
800 ElementAttributeData* otherAttributeData = other->updatedAttributeData();
802 return attributeData->isEquivalent(otherAttributeData);
803 if (otherAttributeData)
804 return otherAttributeData->isEquivalent(attributeData);
808 String Element::nodeName() const
810 return m_tagName.toString();
813 String Element::nodeNamePreservingCase() const
815 return m_tagName.toString();
818 void Element::setPrefix(const AtomicString& prefix, ExceptionCode& ec)
821 checkSetPrefix(prefix, ec);
825 m_tagName.setPrefix(prefix.isEmpty() ? AtomicString() : prefix);
828 KURL Element::baseURI() const
830 const AtomicString& baseAttribute = getAttribute(baseAttr);
831 KURL base(KURL(), baseAttribute);
832 if (!base.protocol().isEmpty())
835 ContainerNode* parent = parentNode();
839 const KURL& parentBase = parent->baseURI();
840 if (parentBase.isNull())
843 return KURL(parentBase, baseAttribute);
846 void Element::createAttributeData() const
848 m_attributeData = ElementAttributeData::create();
851 const QualifiedName& Element::imageSourceAttributeName() const
856 RenderObject* Element::createRenderer(RenderArena* arena, RenderStyle* style)
858 if (document()->documentElement() == this && style->display() == NONE) {
859 // Ignore display: none on root elements. Force a display of block in that case.
860 RenderBlock* result = new (arena) RenderBlock(this);
862 result->setAnimatableStyle(style);
865 return RenderObject::createObject(this, style);
868 bool Element::wasChangedSinceLastFormControlChangeEvent() const
873 void Element::setChangedSinceLastFormControlChangeEvent(bool)
877 Node::InsertionNotificationRequest Element::insertedInto(ContainerNode* insertionPoint)
879 // need to do superclass processing first so inDocument() is true
880 // by the time we reach updateId
881 ContainerNode::insertedInto(insertionPoint);
883 #if ENABLE(FULLSCREEN_API)
884 if (containsFullScreenElement() && parentElement() && !parentElement()->containsFullScreenElement())
885 setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(true);
888 if (!insertionPoint->inDocument())
889 return InsertionDone;
891 const AtomicString& idValue = getIdAttribute();
892 if (!idValue.isNull())
893 updateId(nullAtom, idValue);
895 const AtomicString& nameValue = getNameAttribute();
896 if (!nameValue.isNull())
897 updateName(nullAtom, nameValue);
899 return InsertionDone;
902 static inline TreeScope* treeScopeOfParent(Node* node, ContainerNode* insertionPoint)
904 if (Node* parent = node->parentNode())
906 return insertionPoint->treeScope();
910 void Element::removedFrom(ContainerNode* insertionPoint)
912 #if ENABLE(FULLSCREEN_API)
913 if (containsFullScreenElement())
914 setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false);
916 #if ENABLE(POINTER_LOCK)
917 if (document()->page())
918 document()->page()->pointerLockController()->elementRemoved(this);
921 setSavedLayerScrollOffset(IntSize());
923 if (insertionPoint->inDocument()) {
924 const AtomicString& idValue = getIdAttribute();
925 if (!idValue.isNull() && inDocument())
926 updateId(treeScopeOfParent(this, insertionPoint), idValue, nullAtom);
928 const AtomicString& nameValue = getNameAttribute();
929 if (!nameValue.isNull())
930 updateName(nameValue, nullAtom);
933 ContainerNode::removedFrom(insertionPoint);
936 void Element::attach()
938 suspendPostAttachCallbacks();
939 RenderWidget::suspendWidgetHierarchyUpdates();
941 createRendererIfNeeded();
942 StyleResolverParentPusher parentPusher(this);
944 if (parentElement() && parentElement()->isInCanvasSubtree())
945 setIsInCanvasSubtree(true);
947 // When a shadow root exists, it does the work of attaching the children.
948 if (ElementShadow* shadow = this->shadow()) {
951 attachChildrenIfNeeded();
956 ContainerNode::attach();
960 ElementRareData* data = elementRareData();
961 if (data->needsFocusAppearanceUpdateSoonAfterAttach()) {
962 if (isFocusable() && document()->focusedNode() == this)
963 document()->updateFocusAppearanceSoon(false /* don't restore selection */);
964 data->setNeedsFocusAppearanceUpdateSoonAfterAttach(false);
968 RenderWidget::resumeWidgetHierarchyUpdates();
969 resumePostAttachCallbacks();
972 void Element::unregisterNamedFlowContentNode()
974 if (document()->cssRegionsEnabled() && inNamedFlow()) {
975 if (document()->renderer() && document()->renderer()->view())
976 document()->renderer()->view()->flowThreadController()->unregisterNamedFlowContentNode(this);
980 void Element::detach()
982 RenderWidget::suspendWidgetHierarchyUpdates();
983 unregisterNamedFlowContentNode();
984 cancelFocusAppearanceUpdate();
986 setIsInCanvasSubtree(false);
987 elementRareData()->resetComputedStyle();
990 if (ElementShadow* shadow = this->shadow()) {
991 detachChildrenIfNeeded();
995 ContainerNode::detach();
997 RenderWidget::resumeWidgetHierarchyUpdates();
1000 bool Element::pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle)
1002 ASSERT(currentStyle == renderStyle());
1004 if (!renderer() || !currentStyle)
1007 const PseudoStyleCache* pseudoStyleCache = currentStyle->cachedPseudoStyles();
1008 if (!pseudoStyleCache)
1011 size_t cacheSize = pseudoStyleCache->size();
1012 for (size_t i = 0; i < cacheSize; ++i) {
1013 RefPtr<RenderStyle> newPseudoStyle;
1014 PseudoId pseudoId = pseudoStyleCache->at(i)->styleType();
1015 if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED)
1016 newPseudoStyle = renderer()->uncachedFirstLineStyle(newStyle);
1018 newPseudoStyle = renderer()->getUncachedPseudoStyle(pseudoId, newStyle, newStyle);
1019 if (!newPseudoStyle)
1021 if (*newPseudoStyle != *pseudoStyleCache->at(i)) {
1022 if (pseudoId < FIRST_INTERNAL_PSEUDOID)
1023 newStyle->setHasPseudoStyle(pseudoId);
1024 newStyle->addCachedPseudoStyle(newPseudoStyle);
1025 if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED) {
1026 // FIXME: We should do an actual diff to determine whether a repaint vs. layout
1027 // is needed, but for now just assume a layout will be required. The diff code
1028 // in RenderObject::setStyle would need to be factored out so that it could be reused.
1029 renderer()->setNeedsLayoutAndPrefWidthsRecalc();
1037 PassRefPtr<RenderStyle> Element::styleForRenderer()
1039 if (hasCustomCallbacks()) {
1040 if (RefPtr<RenderStyle> style = customStyleForRenderer())
1041 return style.release();
1044 return document()->styleResolver()->styleForElement(this);
1047 void Element::recalcStyle(StyleChange change)
1049 if (hasCustomCallbacks()) {
1050 if (!willRecalcStyle(change))
1054 // Ref currentStyle in case it would otherwise be deleted when setRenderStyle() is called.
1055 RefPtr<RenderStyle> currentStyle(renderStyle());
1056 bool hasParentStyle = parentNodeForRenderingAndStyle() ? static_cast<bool>(parentNodeForRenderingAndStyle()->renderStyle()) : false;
1057 bool hasDirectAdjacentRules = currentStyle && currentStyle->childrenAffectedByDirectAdjacentRules();
1058 bool hasIndirectAdjacentRules = currentStyle && currentStyle->childrenAffectedByForwardPositionalRules();
1060 if ((change > NoChange || needsStyleRecalc())) {
1061 if (hasRareData()) {
1062 ElementRareData* data = elementRareData();
1063 data->resetComputedStyle();
1064 data->m_styleAffectedByEmpty = false;
1067 if (hasParentStyle && (change >= Inherit || needsStyleRecalc())) {
1068 RefPtr<RenderStyle> newStyle = styleForRenderer();
1069 StyleChange ch = Node::diff(currentStyle.get(), newStyle.get(), document());
1070 if (ch == Detach || !currentStyle) {
1071 // FIXME: The style gets computed twice by calling attach. We could do better if we passed the style along.
1073 // attach recalculates the style for all children. No need to do it twice.
1074 clearNeedsStyleRecalc();
1075 clearChildNeedsStyleRecalc();
1077 if (hasCustomCallbacks())
1078 didRecalcStyle(change);
1083 // Preserve "affected by" bits that were propagated to us from descendants in the case where we didn't do a full
1084 // style change (e.g., only inline style changed).
1085 if (currentStyle->affectedByHoverRules())
1086 newStyle->setAffectedByHoverRules(true);
1087 if (currentStyle->affectedByActiveRules())
1088 newStyle->setAffectedByActiveRules(true);
1089 if (currentStyle->affectedByDragRules())
1090 newStyle->setAffectedByDragRules(true);
1091 if (currentStyle->childrenAffectedByForwardPositionalRules())
1092 newStyle->setChildrenAffectedByForwardPositionalRules();
1093 if (currentStyle->childrenAffectedByBackwardPositionalRules())
1094 newStyle->setChildrenAffectedByBackwardPositionalRules();
1095 if (currentStyle->childrenAffectedByFirstChildRules())
1096 newStyle->setChildrenAffectedByFirstChildRules();
1097 if (currentStyle->childrenAffectedByLastChildRules())
1098 newStyle->setChildrenAffectedByLastChildRules();
1099 if (currentStyle->childrenAffectedByDirectAdjacentRules())
1100 newStyle->setChildrenAffectedByDirectAdjacentRules();
1103 if (ch != NoChange || pseudoStyleCacheIsInvalid(currentStyle.get(), newStyle.get()) || (change == Force && renderer() && renderer()->requiresForcedStyleRecalcPropagation())) {
1104 setRenderStyle(newStyle);
1105 } else if (needsStyleRecalc() && styleChangeType() != SyntheticStyleChange) {
1106 // Although no change occurred, we use the new style so that the cousin style sharing code won't get
1107 // fooled into believing this style is the same.
1109 renderer()->setStyleInternal(newStyle.get());
1111 setRenderStyle(newStyle);
1112 } else if (styleChangeType() == SyntheticStyleChange)
1113 setRenderStyle(newStyle);
1115 // If "rem" units are used anywhere in the document, and if the document element's font size changes, then go ahead and force font updating
1116 // all the way down the tree. This is simpler than having to maintain a cache of objects (and such font size changes should be rare anyway).
1117 if (document()->usesRemUnits() && document()->documentElement() == this && ch != NoChange && currentStyle && newStyle && currentStyle->fontSize() != newStyle->fontSize()) {
1118 // Cached RenderStyles may depend on the rem units.
1119 document()->styleResolver()->invalidateMatchedPropertiesCache();
1123 if (change != Force) {
1124 if (styleChangeType() >= FullStyleChange)
1130 StyleResolverParentPusher parentPusher(this);
1132 // FIXME: This does not care about sibling combinators. Will be necessary in XBL2 world.
1133 if (ElementShadow* shadow = this->shadow()) {
1134 if (change >= Inherit || shadow->childNeedsStyleRecalc() || shadow->needsStyleRecalc()) {
1135 parentPusher.push();
1136 shadow->recalcStyle(change);
1140 // FIXME: This check is good enough for :hover + foo, but it is not good enough for :hover + foo + bar.
1141 // For now we will just worry about the common case, since it's a lot trickier to get the second case right
1142 // without doing way too much re-resolution.
1143 bool forceCheckOfNextElementSibling = false;
1144 bool forceCheckOfAnyElementSibling = false;
1145 for (Node *n = firstChild(); n; n = n->nextSibling()) {
1146 if (n->isTextNode()) {
1147 toText(n)->recalcTextStyle(change);
1150 if (!n->isElementNode())
1152 Element* element = static_cast<Element*>(n);
1153 bool childRulesChanged = element->needsStyleRecalc() && element->styleChangeType() == FullStyleChange;
1154 if ((forceCheckOfNextElementSibling || forceCheckOfAnyElementSibling))
1155 element->setNeedsStyleRecalc();
1156 if (change >= Inherit || element->childNeedsStyleRecalc() || element->needsStyleRecalc()) {
1157 parentPusher.push();
1158 element->recalcStyle(change);
1160 forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjacentRules;
1161 forceCheckOfAnyElementSibling = forceCheckOfAnyElementSibling || (childRulesChanged && hasIndirectAdjacentRules);
1164 clearNeedsStyleRecalc();
1165 clearChildNeedsStyleRecalc();
1167 if (hasCustomCallbacks())
1168 didRecalcStyle(change);
1171 ElementShadow* Element::shadow() const
1176 return elementRareData()->m_shadow.get();
1179 ElementShadow* Element::ensureShadow()
1181 if (ElementShadow* shadow = ensureElementRareData()->m_shadow.get())
1184 elementRareData()->m_shadow = adoptPtr(new ElementShadow());
1185 return elementRareData()->m_shadow.get();
1188 ShadowRoot* Element::ensureShadowRoot()
1190 if (ElementShadow* shadow = this->shadow())
1191 return shadow->oldestShadowRoot();
1193 return ShadowRoot::create(this, ShadowRoot::UserAgentShadowRoot).get();
1196 const AtomicString& Element::shadowPseudoId() const
1198 return hasRareData() ? elementRareData()->m_shadowPseudoId : nullAtom;
1201 void Element::setShadowPseudoId(const AtomicString& id, ExceptionCode& ec)
1203 if (!hasRareData() && id == nullAtom)
1206 if (!CSSSelector::isUnknownPseudoType(id)) {
1211 ensureElementRareData()->m_shadowPseudoId = id;
1214 bool Element::childTypeAllowed(NodeType type) const
1220 case PROCESSING_INSTRUCTION_NODE:
1221 case CDATA_SECTION_NODE:
1222 case ENTITY_REFERENCE_NODE:
1230 static void checkForEmptyStyleChange(Element* element, RenderStyle* style)
1232 if (!style && !element->styleAffectedByEmpty())
1235 if (!style || (style->affectedByEmpty() && (!style->emptyState() || element->hasChildNodes())))
1236 element->setNeedsStyleRecalc();
1239 static void checkForSiblingStyleChanges(Element* e, RenderStyle* style, bool finishedParsingCallback,
1240 Node* beforeChange, Node* afterChange, int childCountDelta)
1243 checkForEmptyStyleChange(e, style);
1245 if (!style || (e->needsStyleRecalc() && style->childrenAffectedByPositionalRules()))
1248 // :first-child. In the parser callback case, we don't have to check anything, since we were right the first time.
1249 // In the DOM case, we only need to do something if |afterChange| is not 0.
1250 // |afterChange| is 0 in the parser case, so it works out that we'll skip this block.
1251 if (style->childrenAffectedByFirstChildRules() && afterChange) {
1252 // Find our new first child.
1253 Node* newFirstChild = 0;
1254 for (newFirstChild = e->firstChild(); newFirstChild && !newFirstChild->isElementNode(); newFirstChild = newFirstChild->nextSibling()) {};
1256 // Find the first element node following |afterChange|
1257 Node* firstElementAfterInsertion = 0;
1258 for (firstElementAfterInsertion = afterChange;
1259 firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode();
1260 firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {};
1262 // This is the insert/append case.
1263 if (newFirstChild != firstElementAfterInsertion && firstElementAfterInsertion && firstElementAfterInsertion->attached() &&
1264 firstElementAfterInsertion->renderStyle() && firstElementAfterInsertion->renderStyle()->firstChildState())
1265 firstElementAfterInsertion->setNeedsStyleRecalc();
1267 // We also have to handle node removal.
1268 if (childCountDelta < 0 && newFirstChild == firstElementAfterInsertion && newFirstChild && (!newFirstChild->renderStyle() || !newFirstChild->renderStyle()->firstChildState()))
1269 newFirstChild->setNeedsStyleRecalc();
1272 // :last-child. In the parser callback case, we don't have to check anything, since we were right the first time.
1273 // In the DOM case, we only need to do something if |afterChange| is not 0.
1274 if (style->childrenAffectedByLastChildRules() && beforeChange) {
1275 // Find our new last child.
1276 Node* newLastChild = 0;
1277 for (newLastChild = e->lastChild(); newLastChild && !newLastChild->isElementNode(); newLastChild = newLastChild->previousSibling()) {};
1279 // Find the last element node going backwards from |beforeChange|
1280 Node* lastElementBeforeInsertion = 0;
1281 for (lastElementBeforeInsertion = beforeChange;
1282 lastElementBeforeInsertion && !lastElementBeforeInsertion->isElementNode();
1283 lastElementBeforeInsertion = lastElementBeforeInsertion->previousSibling()) {};
1285 if (newLastChild != lastElementBeforeInsertion && lastElementBeforeInsertion && lastElementBeforeInsertion->attached() &&
1286 lastElementBeforeInsertion->renderStyle() && lastElementBeforeInsertion->renderStyle()->lastChildState())
1287 lastElementBeforeInsertion->setNeedsStyleRecalc();
1289 // 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
1291 if ((childCountDelta < 0 || finishedParsingCallback) && newLastChild == lastElementBeforeInsertion && newLastChild && (!newLastChild->renderStyle() || !newLastChild->renderStyle()->lastChildState()))
1292 newLastChild->setNeedsStyleRecalc();
1295 // The + selector. We need to invalidate the first element following the insertion point. It is the only possible element
1296 // that could be affected by this DOM change.
1297 if (style->childrenAffectedByDirectAdjacentRules() && afterChange) {
1298 Node* firstElementAfterInsertion = 0;
1299 for (firstElementAfterInsertion = afterChange;
1300 firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode();
1301 firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {};
1302 if (firstElementAfterInsertion && firstElementAfterInsertion->attached())
1303 firstElementAfterInsertion->setNeedsStyleRecalc();
1306 // Forward positional selectors include the ~ selector, nth-child, nth-of-type, first-of-type and only-of-type.
1307 // Backward positional selectors include nth-last-child, nth-last-of-type, last-of-type and only-of-type.
1308 // We have to invalidate everything following the insertion point in the forward case, and everything before the insertion point in the
1310 // |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.
1311 // 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
1312 // here. recalcStyle will then force a walk of the children when it sees that this has happened.
1313 if ((style->childrenAffectedByForwardPositionalRules() && afterChange) ||
1314 (style->childrenAffectedByBackwardPositionalRules() && beforeChange))
1315 e->setNeedsStyleRecalc();
1318 void Element::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
1320 ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
1321 if (changedByParser)
1322 checkForEmptyStyleChange(this, renderStyle());
1324 checkForSiblingStyleChanges(this, renderStyle(), false, beforeChange, afterChange, childCountDelta);
1326 if (ElementShadow * shadow = this->shadow())
1327 shadow->invalidateDistribution();
1330 void Element::beginParsingChildren()
1332 clearIsParsingChildrenFinished();
1333 StyleResolver* styleResolver = document()->styleResolverIfExists();
1334 if (styleResolver && attached())
1335 styleResolver->pushParentElement(this);
1338 void Element::finishParsingChildren()
1340 ContainerNode::finishParsingChildren();
1341 setIsParsingChildrenFinished();
1342 checkForSiblingStyleChanges(this, renderStyle(), true, lastChild(), 0, 0);
1343 if (StyleResolver* styleResolver = document()->styleResolverIfExists())
1344 styleResolver->popParentElement(this);
1348 void Element::formatForDebugger(char* buffer, unsigned length) const
1354 if (s.length() > 0) {
1358 s = getIdAttribute();
1359 if (s.length() > 0) {
1360 if (result.length() > 0)
1366 s = getAttribute(classAttr);
1367 if (s.length() > 0) {
1368 if (result.length() > 0)
1374 strncpy(buffer, result.utf8().data(), length - 1);
1378 PassRefPtr<Attr> Element::setAttributeNode(Attr* attr, ExceptionCode& ec)
1381 ec = TYPE_MISMATCH_ERR;
1385 ElementAttributeData* attributeData = ensureUpdatedAttributeData();
1387 RefPtr<Attr> oldAttr = attrIfExists(attr->qualifiedName());
1388 if (oldAttr.get() == attr)
1389 return attr; // This Attr is already attached to the element.
1391 // INUSE_ATTRIBUTE_ERR: Raised if node is an Attr that is already an attribute of another Element object.
1392 // The DOM user must explicitly clone Attr nodes to re-use them in other elements.
1393 if (attr->ownerElement()) {
1394 ec = INUSE_ATTRIBUTE_ERR;
1398 size_t index = attributeData->getAttributeItemIndex(attr->qualifiedName());
1399 Attribute* oldAttribute = index != notFound ? attributeData->attributeItem(index) : 0;
1401 if (!oldAttribute) {
1402 attributeData->addAttribute(Attribute(attr->qualifiedName(), attr->value()), this);
1403 attributeData->setAttr(this, attr->qualifiedName(), attr);
1408 oldAttr->detachFromElementWithValue(oldAttribute->value());
1410 oldAttr = Attr::create(document(), oldAttribute->name(), oldAttribute->value());
1412 attributeData->replaceAttribute(index, Attribute(attr->name(), attr->value()), this);
1413 attributeData->setAttr(this, attr->qualifiedName(), attr);
1414 return oldAttr.release();
1417 PassRefPtr<Attr> Element::setAttributeNodeNS(Attr* attr, ExceptionCode& ec)
1419 return setAttributeNode(attr, ec);
1422 PassRefPtr<Attr> Element::removeAttributeNode(Attr* attr, ExceptionCode& ec)
1425 ec = TYPE_MISMATCH_ERR;
1428 if (attr->ownerElement() != this) {
1433 ASSERT(document() == attr->document());
1435 ElementAttributeData* attributeData = updatedAttributeData();
1436 ASSERT(attributeData);
1438 size_t index = attributeData->getAttributeItemIndex(attr->qualifiedName());
1439 if (index == notFound) {
1444 return detachAttribute(index);
1447 void Element::setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode& ec, FragmentScriptingPermission scriptingPermission)
1449 String prefix, localName;
1450 if (!Document::parseQualifiedName(qualifiedName, prefix, localName, ec))
1453 QualifiedName qName(prefix, localName, namespaceURI);
1455 if (!Document::hasValidNamespaceForAttributes(qName)) {
1460 if (scriptingPermission == DisallowScriptingContent && (isEventHandlerAttribute(qName) || isAttributeToRemove(qName, value)))
1463 setAttribute(qName, value);
1466 void Element::removeAttribute(size_t index)
1468 ASSERT(attributeData());
1469 ASSERT(index <= attributeCount());
1470 attributeData()->removeAttribute(index, this);
1473 void Element::removeAttribute(const String& name)
1475 ElementAttributeData* attributeData = this->attributeData();
1479 String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
1480 size_t index = attributeData->getAttributeItemIndex(localName, false);
1481 if (index == notFound)
1484 attributeData->removeAttribute(index, this);
1487 void Element::removeAttributeNS(const String& namespaceURI, const String& localName)
1489 removeAttribute(QualifiedName(nullAtom, localName, namespaceURI));
1492 PassRefPtr<Attr> Element::getAttributeNode(const String& name)
1494 ElementAttributeData* attributeData = updatedAttributeData();
1497 return attributeData->getAttributeNode(name, shouldIgnoreAttributeCase(this), this);
1500 PassRefPtr<Attr> Element::getAttributeNodeNS(const String& namespaceURI, const String& localName)
1502 ElementAttributeData* attributeData = updatedAttributeData();
1505 return attributeData->getAttributeNode(QualifiedName(nullAtom, localName, namespaceURI), this);
1508 bool Element::hasAttribute(const String& name) const
1510 ElementAttributeData* attributeData = updatedAttributeData();
1514 // This call to String::lower() seems to be required but
1515 // there may be a way to remove it.
1516 String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
1517 return attributeData->getAttributeItem(localName, false);
1520 bool Element::hasAttributeNS(const String& namespaceURI, const String& localName) const
1522 ElementAttributeData* attributeData = updatedAttributeData();
1525 return attributeData->getAttributeItem(QualifiedName(nullAtom, localName, namespaceURI));
1528 CSSStyleDeclaration *Element::style()
1533 void Element::focus(bool restorePreviousSelection)
1538 Document* doc = document();
1539 if (doc->focusedNode() == this)
1542 // If the stylesheets have already been loaded we can reliably check isFocusable.
1543 // If not, we continue and set the focused node on the focus controller below so
1544 // that it can be updated soon after attach.
1545 if (doc->haveStylesheetsLoaded()) {
1546 doc->updateLayoutIgnorePendingStylesheets();
1551 if (!supportsFocus())
1554 RefPtr<Node> protect;
1555 if (Page* page = doc->page()) {
1556 // Focus and change event handlers can cause us to lose our last ref.
1557 // If a focus event handler changes the focus to a different node it
1558 // does not make sense to continue and update appearence.
1560 if (!page->focusController()->setFocusedNode(this, doc->frame()))
1564 // Setting the focused node above might have invalidated the layout due to scripts.
1565 doc->updateLayoutIgnorePendingStylesheets();
1567 if (!isFocusable()) {
1568 ensureElementRareData()->setNeedsFocusAppearanceUpdateSoonAfterAttach(true);
1572 cancelFocusAppearanceUpdate();
1573 updateFocusAppearance(restorePreviousSelection);
1576 void Element::updateFocusAppearance(bool /*restorePreviousSelection*/)
1578 if (isRootEditableElement()) {
1579 Frame* frame = document()->frame();
1583 // When focusing an editable element in an iframe, don't reset the selection if it already contains a selection.
1584 if (this == frame->selection()->rootEditableElement())
1587 // FIXME: We should restore the previous selection if there is one.
1588 VisibleSelection newSelection = VisibleSelection(firstPositionInOrBeforeNode(this), DOWNSTREAM);
1590 if (frame->selection()->shouldChangeSelection(newSelection)) {
1591 frame->selection()->setSelection(newSelection);
1592 frame->selection()->revealSelection();
1594 } else if (renderer() && !renderer()->isWidget())
1595 renderer()->scrollRectToVisible(getRect());
1598 void Element::blur()
1600 cancelFocusAppearanceUpdate();
1601 Document* doc = document();
1602 if (treeScope()->focusedNode() == this) {
1604 doc->frame()->page()->focusController()->setFocusedNode(0, doc->frame());
1606 doc->setFocusedNode(0);
1610 String Element::innerText()
1612 // We need to update layout, since plainText uses line boxes in the render tree.
1613 document()->updateLayoutIgnorePendingStylesheets();
1616 return textContent(true);
1618 return plainText(rangeOfContents(const_cast<Element*>(this)).get());
1621 String Element::outerText()
1623 // Getting outerText is the same as getting innerText, only
1624 // setting is different. You would think this should get the plain
1625 // text for the outer range, but this is wrong, <br> for instance
1626 // would return different values for inner and outer text by such
1627 // a rule, but it doesn't in WinIE, and we want to match that.
1631 String Element::title() const
1636 LayoutSize Element::minimumSizeForResizing() const
1638 return hasRareData() ? elementRareData()->m_minimumSizeForResizing : defaultMinimumSizeForResizing();
1641 void Element::setMinimumSizeForResizing(const LayoutSize& size)
1643 if (size == defaultMinimumSizeForResizing() && !hasRareData())
1645 ensureElementRareData()->m_minimumSizeForResizing = size;
1648 RenderStyle* Element::computedStyle(PseudoId pseudoElementSpecifier)
1650 // FIXME: Find and use the renderer from the pseudo element instead of the actual element so that the 'length'
1651 // properties, which are only known by the renderer because it did the layout, will be correct and so that the
1652 // values returned for the ":selection" pseudo-element will be correct.
1653 if (RenderStyle* usedStyle = renderStyle()) {
1654 if (pseudoElementSpecifier) {
1655 RenderStyle* cachedPseudoStyle = usedStyle->getCachedPseudoStyle(pseudoElementSpecifier);
1656 return cachedPseudoStyle ? cachedPseudoStyle : usedStyle;
1662 // FIXME: Try to do better than this. Ensure that styleForElement() works for elements that are not in the
1663 // document tree and figure out when to destroy the computed style for such elements.
1666 ElementRareData* data = ensureElementRareData();
1667 if (!data->m_computedStyle)
1668 data->m_computedStyle = document()->styleForElementIgnoringPendingStylesheets(this);
1669 return pseudoElementSpecifier ? data->m_computedStyle->getCachedPseudoStyle(pseudoElementSpecifier) : data->m_computedStyle.get();
1672 void Element::setStyleAffectedByEmpty()
1674 ElementRareData* data = ensureElementRareData();
1675 data->m_styleAffectedByEmpty = true;
1678 bool Element::styleAffectedByEmpty() const
1680 return hasRareData() && elementRareData()->m_styleAffectedByEmpty;
1683 void Element::setIsInCanvasSubtree(bool isInCanvasSubtree)
1685 ElementRareData* data = ensureElementRareData();
1686 data->m_isInCanvasSubtree = isInCanvasSubtree;
1689 bool Element::isInCanvasSubtree() const
1691 return hasRareData() && elementRareData()->m_isInCanvasSubtree;
1694 AtomicString Element::computeInheritedLanguage() const
1696 const Node* n = this;
1698 // The language property is inherited, so we iterate over the parents to find the first language.
1699 while (n && value.isNull()) {
1700 if (n->isElementNode()) {
1701 // Spec: xml:lang takes precedence -- http://www.w3.org/TR/xhtml1/#C_7
1702 value = static_cast<const Element*>(n)->fastGetAttribute(XMLNames::langAttr);
1704 value = static_cast<const Element*>(n)->fastGetAttribute(HTMLNames::langAttr);
1705 } else if (n->isDocumentNode()) {
1706 // checking the MIME content-language
1707 value = static_cast<const Document*>(n)->contentLanguage();
1710 n = n->parentNode();
1716 void Element::cancelFocusAppearanceUpdate()
1719 elementRareData()->setNeedsFocusAppearanceUpdateSoonAfterAttach(false);
1720 if (document()->focusedNode() == this)
1721 document()->cancelFocusAppearanceUpdate();
1724 void Element::normalizeAttributes()
1729 ElementAttributeData* attributeData = updatedAttributeData();
1730 ASSERT(attributeData);
1732 const Vector<Attribute>& attributes = attributeData->attributeVector();
1733 for (size_t i = 0; i < attributes.size(); ++i) {
1734 if (RefPtr<Attr> attr = attrIfExists(attributes[i].name()))
1739 // ElementTraversal API
1740 Element* Element::firstElementChild() const
1742 return WebCore::firstElementChild(this);
1745 Element* Element::lastElementChild() const
1747 Node* n = lastChild();
1748 while (n && !n->isElementNode())
1749 n = n->previousSibling();
1750 return static_cast<Element*>(n);
1753 unsigned Element::childElementCount() const
1756 Node* n = firstChild();
1758 count += n->isElementNode();
1759 n = n->nextSibling();
1764 bool Element::webkitMatchesSelector(const String& selector, ExceptionCode& ec)
1766 if (selector.isEmpty()) {
1771 SelectorQuery* selectorQuery = document()->selectorQueryCache()->add(selector, document(), ec);
1774 return selectorQuery->matches(this);
1777 DOMTokenList* Element::classList()
1779 ElementRareData* data = ensureElementRareData();
1780 if (!data->m_classList)
1781 data->m_classList = ClassList::create(this);
1782 return data->m_classList.get();
1785 DOMTokenList* Element::optionalClassList() const
1789 return elementRareData()->m_classList.get();
1792 DOMStringMap* Element::dataset()
1794 ElementRareData* data = ensureElementRareData();
1795 if (!data->m_datasetDOMStringMap)
1796 data->m_datasetDOMStringMap = DatasetDOMStringMap::create(this);
1797 return data->m_datasetDOMStringMap.get();
1800 KURL Element::getURLAttribute(const QualifiedName& name) const
1802 #if !ASSERT_DISABLED
1803 if (m_attributeData) {
1804 if (Attribute* attribute = getAttributeItem(name))
1805 ASSERT(isURLAttribute(*attribute));
1808 return document()->completeURL(stripLeadingAndTrailingHTMLSpaces(getAttribute(name)));
1811 KURL Element::getNonEmptyURLAttribute(const QualifiedName& name) const
1813 #if !ASSERT_DISABLED
1814 if (m_attributeData) {
1815 if (Attribute* attribute = getAttributeItem(name))
1816 ASSERT(isURLAttribute(*attribute));
1819 String value = stripLeadingAndTrailingHTMLSpaces(getAttribute(name));
1820 if (value.isEmpty())
1822 return document()->completeURL(value);
1825 int Element::getIntegralAttribute(const QualifiedName& attributeName) const
1827 return getAttribute(attributeName).string().toInt();
1830 void Element::setIntegralAttribute(const QualifiedName& attributeName, int value)
1832 // FIXME: Need an AtomicString version of String::number.
1833 setAttribute(attributeName, String::number(value));
1836 unsigned Element::getUnsignedIntegralAttribute(const QualifiedName& attributeName) const
1838 return getAttribute(attributeName).string().toUInt();
1841 void Element::setUnsignedIntegralAttribute(const QualifiedName& attributeName, unsigned value)
1843 // FIXME: Need an AtomicString version of String::number.
1844 setAttribute(attributeName, String::number(value));
1848 bool Element::childShouldCreateRenderer(const NodeRenderingContext& childContext) const
1850 // Only create renderers for SVG elements whose parents are SVG elements, or for proper <svg xmlns="svgNS"> subdocuments.
1851 if (childContext.node()->isSVGElement())
1852 return childContext.node()->hasTagName(SVGNames::svgTag) || isSVGElement();
1854 return Node::childShouldCreateRenderer(childContext);
1858 #if ENABLE(FULLSCREEN_API)
1859 void Element::webkitRequestFullscreen()
1861 document()->requestFullScreenForElement(this, ALLOW_KEYBOARD_INPUT, Document::EnforceIFrameAllowFulScreenRequirement);
1864 void Element::webkitRequestFullScreen(unsigned short flags)
1866 document()->requestFullScreenForElement(this, (flags | LEGACY_MOZILLA_REQUEST), Document::EnforceIFrameAllowFulScreenRequirement);
1869 bool Element::containsFullScreenElement() const
1871 return hasRareData() ? elementRareData()->m_containsFullScreenElement : false;
1874 void Element::setContainsFullScreenElement(bool flag)
1876 ensureElementRareData()->m_containsFullScreenElement = flag;
1877 setNeedsStyleRecalc(SyntheticStyleChange);
1880 static Element* parentCrossingFrameBoundaries(Element* element)
1883 return element->parentElement() ? element->parentElement() : element->document()->ownerElement();
1886 void Element::setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(bool flag)
1888 Element* element = this;
1889 while ((element = parentCrossingFrameBoundaries(element)))
1890 element->setContainsFullScreenElement(flag);
1894 #if ENABLE(POINTER_LOCK)
1895 void Element::webkitRequestPointerLock()
1897 if (document()->page())
1898 document()->page()->pointerLockController()->requestPointerLock(this, 0, 0);
1902 SpellcheckAttributeState Element::spellcheckAttributeState() const
1904 const AtomicString& value = getAttribute(HTMLNames::spellcheckAttr);
1905 if (value == nullAtom)
1906 return SpellcheckAttributeDefault;
1907 if (equalIgnoringCase(value, "true") || equalIgnoringCase(value, ""))
1908 return SpellcheckAttributeTrue;
1909 if (equalIgnoringCase(value, "false"))
1910 return SpellcheckAttributeFalse;
1912 return SpellcheckAttributeDefault;
1915 bool Element::isSpellCheckingEnabled() const
1917 const Element* element = this;
1919 switch (element->spellcheckAttributeState()) {
1920 case SpellcheckAttributeTrue:
1922 case SpellcheckAttributeFalse:
1924 case SpellcheckAttributeDefault:
1928 ContainerNode* parent = const_cast<Element*>(element)->parentOrHostNode();
1929 if (parent && parent->isElementNode())
1930 element = toElement(parent);
1931 else if (parent && parent->isShadowRoot())
1932 element = toElement(parent->parentOrHostNode());
1940 PassRefPtr<WebKitAnimationList> Element::webkitGetAnimations() const
1945 AnimationController* animController = renderer()->animation();
1947 if (!animController)
1950 return animController->animationsForRenderer(renderer());
1953 const AtomicString& Element::webkitRegionOverflow() const
1955 document()->updateLayoutIgnorePendingStylesheets();
1957 if (document()->cssRegionsEnabled() && renderer() && renderer()->isRenderRegion()) {
1958 RenderRegion* region = toRenderRegion(renderer());
1959 switch (region->regionState()) {
1960 case RenderRegion::RegionFit: {
1961 DEFINE_STATIC_LOCAL(AtomicString, fitState, ("fit"));
1964 case RenderRegion::RegionEmpty: {
1965 DEFINE_STATIC_LOCAL(AtomicString, emptyState, ("empty"));
1968 case RenderRegion::RegionOverflow: {
1969 DEFINE_STATIC_LOCAL(AtomicString, overflowState, ("overflow"));
1970 return overflowState;
1976 DEFINE_STATIC_LOCAL(AtomicString, undefinedState, ("undefined"));
1977 return undefinedState;
1981 bool Element::fastAttributeLookupAllowed(const QualifiedName& name) const
1983 if (name == HTMLNames::styleAttr)
1988 return !SVGElement::isAnimatableAttribute(name);
1995 #ifdef DUMP_NODE_STATISTICS
1996 bool Element::hasNamedNodeMap() const
1998 return hasRareData() && elementRareData()->m_attributeMap;
2002 void Element::willModifyAttribute(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue)
2004 if (isIdAttributeName(name))
2005 updateId(oldValue, newValue);
2006 else if (name == HTMLNames::nameAttr)
2007 updateName(oldValue, newValue);
2009 #if ENABLE(MUTATION_OBSERVERS)
2010 if (OwnPtr<MutationObserverInterestGroup> recipients = MutationObserverInterestGroup::createForAttributesMutation(this, name))
2011 recipients->enqueueMutationRecord(MutationRecord::createAttributes(this, name, oldValue));
2014 #if ENABLE(INSPECTOR)
2015 InspectorInstrumentation::willModifyDOMAttr(document(), this, oldValue, newValue);
2019 void Element::didAddAttribute(const Attribute& attribute)
2021 attributeChanged(attribute);
2022 InspectorInstrumentation::didModifyDOMAttr(document(), this, attribute.localName(), attribute.value());
2023 dispatchSubtreeModifiedEvent();
2026 void Element::didModifyAttribute(const Attribute& attribute)
2028 attributeChanged(attribute);
2029 InspectorInstrumentation::didModifyDOMAttr(document(), this, attribute.localName(), attribute.value());
2030 // Do not dispatch a DOMSubtreeModified event here; see bug 81141.
2033 void Element::didRemoveAttribute(const QualifiedName& name)
2035 attributeChanged(Attribute(name, nullAtom));
2036 InspectorInstrumentation::didRemoveDOMAttr(document(), this, name.localName());
2037 dispatchSubtreeModifiedEvent();
2041 void Element::updateNamedItemRegistration(const AtomicString& oldName, const AtomicString& newName)
2043 if (!document()->isHTMLDocument())
2046 if (!oldName.isEmpty())
2047 static_cast<HTMLDocument*>(document())->removeNamedItem(oldName);
2049 if (!newName.isEmpty())
2050 static_cast<HTMLDocument*>(document())->addNamedItem(newName);
2053 void Element::updateExtraNamedItemRegistration(const AtomicString& oldId, const AtomicString& newId)
2055 if (!document()->isHTMLDocument())
2058 if (!oldId.isEmpty())
2059 static_cast<HTMLDocument*>(document())->removeExtraNamedItem(oldId);
2061 if (!newId.isEmpty())
2062 static_cast<HTMLDocument*>(document())->addExtraNamedItem(newId);
2065 PassRefPtr<HTMLCollection> Element::ensureCachedHTMLCollection(CollectionType type)
2067 return ensureElementRareData()->ensureCachedHTMLCollection(this, type);
2070 PassRefPtr<HTMLCollection> ElementRareData::ensureCachedHTMLCollection(Element* element, CollectionType type)
2072 if (!m_cachedCollections) {
2073 m_cachedCollections = adoptPtr(new CachedHTMLCollectionArray);
2074 for (unsigned i = 0; i < NumNodeCollectionTypes; i++)
2075 (*m_cachedCollections)[i] = 0;
2078 if (HTMLCollection* collection = (*m_cachedCollections)[type - FirstNodeCollectionType])
2081 RefPtr<HTMLCollection> collection;
2082 if (type == TableRows) {
2083 ASSERT(element->hasTagName(tableTag));
2084 collection = HTMLTableRowsCollection::create(element);
2085 } else if (type == SelectOptions) {
2086 ASSERT(element->hasTagName(selectTag));
2087 collection = HTMLOptionsCollection::create(element);
2088 } else if (type == FormControls) {
2089 ASSERT(element->hasTagName(formTag) || element->hasTagName(fieldsetTag));
2090 collection = HTMLFormCollection::create(element);
2091 #if ENABLE(MICRODATA)
2092 } else if (type == ItemProperties) {
2093 collection = HTMLPropertiesCollection::create(element);
2096 collection = HTMLCollection::create(element, type);
2097 (*m_cachedCollections)[type - FirstNodeCollectionType] = collection.get();
2098 return collection.release();
2101 HTMLCollection* Element::cachedHTMLCollection(CollectionType type)
2103 return hasRareData() ? elementRareData()->cachedHTMLCollection(type) : 0;
2106 void Element::removeCachedHTMLCollection(HTMLCollection* collection, CollectionType type)
2108 ASSERT(hasRareData());
2109 elementRareData()->removeCachedHTMLCollection(collection, type);
2112 IntSize Element::savedLayerScrollOffset() const
2114 return hasRareData() ? elementRareData()->m_savedLayerScrollOffset : IntSize();
2117 void Element::setSavedLayerScrollOffset(const IntSize& size)
2119 if (size.isZero() && !hasRareData())
2121 ensureElementRareData()->m_savedLayerScrollOffset = size;
2124 PassRefPtr<Attr> Element::attrIfExists(const QualifiedName& name)
2128 ASSERT(attributeData());
2129 return attributeData()->attrIfExists(this, name);
2132 PassRefPtr<Attr> Element::ensureAttr(const QualifiedName& name)
2134 ASSERT(attributeData());
2135 return attributeData()->ensureAttr(this, name);
2138 bool Element::willRecalcStyle(StyleChange)
2140 ASSERT(hasCustomCallbacks());
2144 void Element::didRecalcStyle(StyleChange)
2146 ASSERT(hasCustomCallbacks());
2150 PassRefPtr<RenderStyle> Element::customStyleForRenderer()
2152 ASSERT(hasCustomCallbacks());
2157 void Element::cloneAttributesFromElement(const Element& other)
2159 if (ElementAttributeData* attributeData = other.updatedAttributeData())
2160 ensureUpdatedAttributeData()->cloneDataFrom(*attributeData, other, *this);
2161 else if (m_attributeData) {
2162 m_attributeData->clearAttributes(this);
2163 m_attributeData.clear();
2167 void Element::cloneDataFromElement(const Element& other)
2169 cloneAttributesFromElement(other);
2170 copyNonAttributePropertiesFromElement(other);
2173 } // namespace WebCore