summaryrefslogtreecommitdiff
path: root/Source/WebCore/html/HTMLOptionElement.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/html/HTMLOptionElement.cpp
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebCore/html/HTMLOptionElement.cpp')
-rw-r--r--Source/WebCore/html/HTMLOptionElement.cpp157
1 files changed, 60 insertions, 97 deletions
diff --git a/Source/WebCore/html/HTMLOptionElement.cpp b/Source/WebCore/html/HTMLOptionElement.cpp
index f5049b674..8fbe51edb 100644
--- a/Source/WebCore/html/HTMLOptionElement.cpp
+++ b/Source/WebCore/html/HTMLOptionElement.cpp
@@ -3,7 +3,7 @@
* (C) 1999 Antti Koivisto (koivisto@kde.org)
* (C) 2001 Dirk Mueller (mueller@kde.org)
* (C) 2006 Alexey Proskuryakov (ap@nypop.com)
- * Copyright (C) 2004, 2005, 2006, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2004-2017 Apple Inc. All rights reserved.
* Copyright (C) 2010 Google Inc. All rights reserved.
* Copyright (C) 2011 Motorola Mobility, Inc. All rights reserved.
*
@@ -27,9 +27,7 @@
#include "config.h"
#include "HTMLOptionElement.h"
-#include "Attribute.h"
#include "Document.h"
-#include "ExceptionCode.h"
#include "HTMLDataListElement.h"
#include "HTMLNames.h"
#include "HTMLOptGroupElement.h"
@@ -57,79 +55,62 @@ HTMLOptionElement::HTMLOptionElement(const QualifiedName& tagName, Document& doc
setHasCustomStyleResolveCallbacks();
}
-PassRefPtr<HTMLOptionElement> HTMLOptionElement::create(Document& document)
+Ref<HTMLOptionElement> HTMLOptionElement::create(Document& document)
{
- return adoptRef(new HTMLOptionElement(optionTag, document));
+ return adoptRef(*new HTMLOptionElement(optionTag, document));
}
-PassRefPtr<HTMLOptionElement> HTMLOptionElement::create(const QualifiedName& tagName, Document& document)
+Ref<HTMLOptionElement> HTMLOptionElement::create(const QualifiedName& tagName, Document& document)
{
- return adoptRef(new HTMLOptionElement(tagName, document));
+ return adoptRef(*new HTMLOptionElement(tagName, document));
}
-PassRefPtr<HTMLOptionElement> HTMLOptionElement::createForJSConstructor(Document& document, const String& data, const String& value,
- bool defaultSelected, bool selected, ExceptionCode& ec)
+ExceptionOr<Ref<HTMLOptionElement>> HTMLOptionElement::createForJSConstructor(Document& document,
+ const String& data, const String& value, bool defaultSelected, bool selected)
{
- RefPtr<HTMLOptionElement> element = adoptRef(new HTMLOptionElement(optionTag, document));
+ Ref<HTMLOptionElement> element = adoptRef(*new HTMLOptionElement(optionTag, document));
- RefPtr<Text> text = Text::create(document, data.isNull() ? "" : data);
+ auto text = Text::create(document, data.isNull() ? emptyString() : data);
- ec = 0;
- element->appendChild(text.release(), ec);
- if (ec)
- return 0;
+ auto appendResult = element->appendChild(text);
+ if (appendResult.hasException())
+ return appendResult.releaseException();
if (!value.isNull())
element->setValue(value);
if (defaultSelected)
- element->setAttribute(selectedAttr, emptyAtom);
+ element->setAttributeWithoutSynchronization(selectedAttr, emptyAtom);
element->setSelected(selected);
- return element.release();
+ return WTFMove(element);
}
-void HTMLOptionElement::didAttachRenderers()
+bool HTMLOptionElement::isFocusable() const
{
- // If after attaching nothing called styleForRenderer() on this node we
- // manually cache the value. This happens if our parent doesn't have a
- // renderer like <optgroup> or if it doesn't allow children like <select>.
- if (!m_style && parentNode()->renderStyle())
- updateNonRenderStyle();
+ if (!supportsFocus())
+ return false;
+ // Option elements do not have a renderer.
+ auto* style = const_cast<HTMLOptionElement&>(*this).computedStyle();
+ return style && style->display() != NONE;
}
-void HTMLOptionElement::willDetachRenderers()
+bool HTMLOptionElement::matchesDefaultPseudoClass() const
{
- m_style.clear();
-}
-
-bool HTMLOptionElement::isFocusable() const
-{
- // Option elements do not have a renderer so we check the renderStyle instead.
- return supportsFocus() && renderStyle() && renderStyle()->display() != NONE;
+ return hasAttributeWithoutSynchronization(selectedAttr);
}
String HTMLOptionElement::text() const
{
- String text;
-
- // WinIE does not use the label attribute, so as a quirk, we ignore it.
- if (!document().inQuirksMode())
- text = fastGetAttribute(labelAttr);
-
- // FIXME: The following treats an element with the label attribute set to
- // the empty string the same as an element with no label attribute at all.
- // Is that correct? If it is, then should the label function work the same way?
- if (text.isEmpty())
- text = collectOptionInnerText();
+ String text = collectOptionInnerText();
// FIXME: Is displayStringModifiedByEncoding helpful here?
// If it's correct here, then isn't it needed in the value and label functions too?
return document().displayStringModifiedByEncoding(text).stripWhiteSpace(isHTMLSpace).simplifyWhiteSpace(isHTMLSpace);
}
-void HTMLOptionElement::setText(const String &text, ExceptionCode& ec)
+void HTMLOptionElement::setText(const String &text)
{
- Ref<HTMLOptionElement> protectFromMutationEvents(*this);
+ Ref<HTMLOptionElement> protectedThis(*this);
// Changing the text causes a recalc of a select's items, which will reset the selected
// index to the first item if the select is single selection with a menu list. We attempt to
@@ -140,11 +121,11 @@ void HTMLOptionElement::setText(const String &text, ExceptionCode& ec)
// Handle the common special case where there's exactly 1 child node, and it's a text node.
Node* child = firstChild();
- if (child && child->isTextNode() && !child->nextSibling())
- toText(child)->setData(text, ec);
+ if (is<Text>(child) && !child->nextSibling())
+ downcast<Text>(*child).setData(text);
else {
removeChildren();
- appendChild(Text::create(document(), text), ec);
+ appendChild(Text::create(document(), text));
}
if (selectIsMenuList && select->selectedIndex() != oldSelectedIndex)
@@ -168,12 +149,10 @@ int HTMLOptionElement::index() const
int optionIndex = 0;
- const Vector<HTMLElement*>& items = selectElement->listItems();
- size_t length = items.size();
- for (size_t i = 0; i < length; ++i) {
- if (!isHTMLOptionElement(items[i]))
+ for (auto& item : selectElement->listItems()) {
+ if (!is<HTMLOptionElement>(*item))
continue;
- if (items[i] == this)
+ if (item == this)
return optionIndex;
++optionIndex;
}
@@ -193,11 +172,13 @@ void HTMLOptionElement::parseAttribute(const QualifiedName& name, const AtomicSt
bool oldDisabled = m_disabled;
m_disabled = !value.isNull();
if (oldDisabled != m_disabled) {
- didAffectSelector(AffectedSelectorDisabled | AffectedSelectorEnabled);
+ invalidateStyleForSubtree();
if (renderer() && renderer()->style().hasAppearance())
- renderer()->theme().stateChanged(renderer(), EnabledState);
+ renderer()->theme().stateChanged(*renderer(), ControlStates::EnabledState);
}
} else if (name == selectedAttr) {
+ invalidateStyleForSubtree();
+
// FIXME: This doesn't match what the HTML specification says.
// The specification implies that removing the selected attribute or
// changing the value of a selected attribute that is already present
@@ -211,7 +192,7 @@ void HTMLOptionElement::parseAttribute(const QualifiedName& name, const AtomicSt
String HTMLOptionElement::value() const
{
- const AtomicString& value = fastGetAttribute(valueAttr);
+ const AtomicString& value = attributeWithoutSynchronization(valueAttr);
if (!value.isNull())
return value;
return collectOptionInnerText().stripWhiteSpace(isHTMLSpace).simplifyWhiteSpace(isHTMLSpace);
@@ -219,7 +200,7 @@ String HTMLOptionElement::value() const
void HTMLOptionElement::setValue(const String& value)
{
- setAttribute(valueAttr, value);
+ setAttributeWithoutSynchronization(valueAttr, value);
}
bool HTMLOptionElement::selected()
@@ -237,7 +218,7 @@ void HTMLOptionElement::setSelected(bool selected)
setSelectedState(selected);
if (HTMLSelectElement* select = ownerSelectElement())
- select->optionSelectionStateChanged(this, selected);
+ select->optionSelectionStateChanged(*this, selected);
}
void HTMLOptionElement::setSelectedState(bool selected)
@@ -246,7 +227,7 @@ void HTMLOptionElement::setSelectedState(bool selected)
return;
m_isSelected = selected;
- didAffectSelector(AffectedSelectorChecked);
+ invalidateStyleForSubtree();
if (HTMLSelectElement* select = ownerSelectElement())
select->invalidateSelectedItems();
@@ -268,57 +249,39 @@ void HTMLOptionElement::childrenChanged(const ChildChange& change)
HTMLDataListElement* HTMLOptionElement::ownerDataListElement() const
{
for (ContainerNode* parent = parentNode(); parent ; parent = parent->parentNode()) {
- if (parent->hasTagName(datalistTag))
- return toHTMLDataListElement(parent);
+ if (is<HTMLDataListElement>(*parent))
+ return downcast<HTMLDataListElement>(parent);
}
- return 0;
+ return nullptr;
}
#endif
HTMLSelectElement* HTMLOptionElement::ownerSelectElement() const
{
ContainerNode* select = parentNode();
- while (select && !select->hasTagName(selectTag))
+ while (select && !is<HTMLSelectElement>(*select))
select = select->parentNode();
if (!select)
- return 0;
+ return nullptr;
- return toHTMLSelectElement(select);
+ return downcast<HTMLSelectElement>(select);
}
String HTMLOptionElement::label() const
{
- const AtomicString& label = fastGetAttribute(labelAttr);
+ String label = attributeWithoutSynchronization(labelAttr);
if (!label.isNull())
- return label;
+ return label.stripWhiteSpace(isHTMLSpace);
return collectOptionInnerText().stripWhiteSpace(isHTMLSpace).simplifyWhiteSpace(isHTMLSpace);
}
void HTMLOptionElement::setLabel(const String& label)
{
- setAttribute(labelAttr, label);
-}
-
-void HTMLOptionElement::updateNonRenderStyle()
-{
- m_style = document().ensureStyleResolver().styleForElement(this);
-}
-
-RenderStyle* HTMLOptionElement::nonRendererStyle() const
-{
- return m_style.get();
-}
-
-PassRefPtr<RenderStyle> HTMLOptionElement::customStyleForRenderer()
-{
- // styleForRenderer is called whenever a new style should be associated
- // with an Element so now is a good time to update our cached style.
- updateNonRenderStyle();
- return m_style;
+ setAttributeWithoutSynchronization(labelAttr, label);
}
-void HTMLOptionElement::didRecalcStyle(Style::Change)
+void HTMLOptionElement::willResetComputedStyle()
{
// FIXME: This is nasty, we ask our owner select to repaint even if the new
// style is exactly the same.
@@ -331,9 +294,9 @@ void HTMLOptionElement::didRecalcStyle(Style::Change)
String HTMLOptionElement::textIndentedToRespectGroupLabel() const
{
ContainerNode* parent = parentNode();
- if (parent && isHTMLOptGroupElement(parent))
- return " " + text();
- return text();
+ if (is<HTMLOptGroupElement>(parent))
+ return " " + label();
+ return label();
}
bool HTMLOptionElement::isDisabledFormControl() const
@@ -341,23 +304,23 @@ bool HTMLOptionElement::isDisabledFormControl() const
if (ownElementDisabled())
return true;
- if (!parentNode() || !parentNode()->isHTMLElement())
+ if (!is<HTMLOptGroupElement>(parentNode()))
return false;
- HTMLElement& parentElement = toHTMLElement(*parentNode());
- return isHTMLOptGroupElement(parentElement) && parentElement.isDisabledFormControl();
+ return downcast<HTMLOptGroupElement>(*parentNode()).isDisabledFormControl();
}
Node::InsertionNotificationRequest HTMLOptionElement::insertedInto(ContainerNode& insertionPoint)
{
if (HTMLSelectElement* select = ownerSelectElement()) {
select->setRecalcListItems();
+ select->updateValidity();
// Do not call selected() since calling updateListItemSelectedStates()
// at this time won't do the right thing. (Why, exactly?)
// FIXME: Might be better to call this unconditionally, always passing m_isSelected,
// rather than only calling it if we are selected.
if (m_isSelected)
- select->optionSelectionStateChanged(this, true);
+ select->optionSelectionStateChanged(*this, true);
select->scrollToSelection();
}
@@ -368,13 +331,13 @@ String HTMLOptionElement::collectOptionInnerText() const
{
StringBuilder text;
for (Node* node = firstChild(); node; ) {
- if (node->isTextNode())
+ if (is<Text>(*node))
text.append(node->nodeValue());
// Text nodes inside script elements are not part of the option text.
- if (node->isElementNode() && toScriptElementIfPossible(toElement(node)))
- node = NodeTraversal::nextSkippingChildren(node, this);
+ if (is<Element>(*node) && isScriptElement(downcast<Element>(*node)))
+ node = NodeTraversal::nextSkippingChildren(*node, this);
else
- node = NodeTraversal::next(node, this);
+ node = NodeTraversal::next(*node, this);
}
return text.toString();
}