diff options
Diffstat (limited to 'Source/WebCore/html/HTMLTableElement.cpp')
-rw-r--r-- | Source/WebCore/html/HTMLTableElement.cpp | 298 |
1 files changed, 151 insertions, 147 deletions
diff --git a/Source/WebCore/html/HTMLTableElement.cpp b/Source/WebCore/html/HTMLTableElement.cpp index bf22d0087..dc321bcb6 100644 --- a/Source/WebCore/html/HTMLTableElement.cpp +++ b/Source/WebCore/html/HTMLTableElement.cpp @@ -25,19 +25,20 @@ #include "config.h" #include "HTMLTableElement.h" -#include "Attribute.h" #include "CSSImageValue.h" #include "CSSPropertyNames.h" #include "CSSValueKeywords.h" #include "CSSValuePool.h" +#include "ElementChildIterator.h" #include "ExceptionCode.h" -#include "ExceptionCodePlaceholder.h" +#include "GenericCachedHTMLCollection.h" #include "HTMLNames.h" #include "HTMLParserIdioms.h" #include "HTMLTableCaptionElement.h" #include "HTMLTableRowElement.h" #include "HTMLTableRowsCollection.h" #include "HTMLTableSectionElement.h" +#include "NodeRareData.h" #include "RenderTable.h" #include "StyleProperties.h" #include <wtf/Ref.h> @@ -48,162 +49,158 @@ using namespace HTMLNames; HTMLTableElement::HTMLTableElement(const QualifiedName& tagName, Document& document) : HTMLElement(tagName, document) - , m_borderAttr(false) - , m_borderColorAttr(false) - , m_frameAttr(false) - , m_rulesAttr(UnsetRules) - , m_padding(1) { ASSERT(hasTagName(tableTag)); } -PassRefPtr<HTMLTableElement> HTMLTableElement::create(Document& document) +Ref<HTMLTableElement> HTMLTableElement::create(Document& document) { - return adoptRef(new HTMLTableElement(tableTag, document)); + return adoptRef(*new HTMLTableElement(tableTag, document)); } -PassRefPtr<HTMLTableElement> HTMLTableElement::create(const QualifiedName& tagName, Document& document) +Ref<HTMLTableElement> HTMLTableElement::create(const QualifiedName& tagName, Document& document) { - return adoptRef(new HTMLTableElement(tagName, document)); + return adoptRef(*new HTMLTableElement(tagName, document)); } HTMLTableCaptionElement* HTMLTableElement::caption() const { - for (Node* child = firstChild(); child; child = child->nextSibling()) { - if (child->hasTagName(captionTag)) - return toHTMLTableCaptionElement(child); - } - return 0; + return childrenOfType<HTMLTableCaptionElement>(const_cast<HTMLTableElement&>(*this)).first(); } -void HTMLTableElement::setCaption(PassRefPtr<HTMLTableCaptionElement> newCaption, ExceptionCode& ec) +ExceptionOr<void> HTMLTableElement::setCaption(RefPtr<HTMLTableCaptionElement>&& newCaption) { deleteCaption(); - insertBefore(newCaption, firstChild(), ec); + if (!newCaption) + return { }; + return insertBefore(*newCaption, firstChild()); } HTMLTableSectionElement* HTMLTableElement::tHead() const { for (Node* child = firstChild(); child; child = child->nextSibling()) { if (child->hasTagName(theadTag)) - return toHTMLTableSectionElement(child); + return downcast<HTMLTableSectionElement>(child); } - return 0; + return nullptr; } -void HTMLTableElement::setTHead(PassRefPtr<HTMLTableSectionElement> newHead, ExceptionCode& ec) +ExceptionOr<void> HTMLTableElement::setTHead(RefPtr<HTMLTableSectionElement>&& newHead) { + if (UNLIKELY(newHead && !newHead->hasTagName(theadTag))) + return Exception { HIERARCHY_REQUEST_ERR }; + deleteTHead(); + if (!newHead) + return { }; Node* child; - for (child = firstChild(); child; child = child->nextSibling()) + for (child = firstChild(); child; child = child->nextSibling()) { if (child->isElementNode() && !child->hasTagName(captionTag) && !child->hasTagName(colgroupTag)) break; + } - insertBefore(newHead, child, ec); + return insertBefore(*newHead, child); } HTMLTableSectionElement* HTMLTableElement::tFoot() const { for (Node* child = firstChild(); child; child = child->nextSibling()) { if (child->hasTagName(tfootTag)) - return toHTMLTableSectionElement(child); + return downcast<HTMLTableSectionElement>(child); } - return 0; + return nullptr; } -void HTMLTableElement::setTFoot(PassRefPtr<HTMLTableSectionElement> newFoot, ExceptionCode& ec) +ExceptionOr<void> HTMLTableElement::setTFoot(RefPtr<HTMLTableSectionElement>&& newFoot) { + if (UNLIKELY(newFoot && !newFoot->hasTagName(tfootTag))) + return Exception { HIERARCHY_REQUEST_ERR }; deleteTFoot(); - - Node* child; - for (child = firstChild(); child; child = child->nextSibling()) - if (child->isElementNode() && !child->hasTagName(captionTag) && !child->hasTagName(colgroupTag) && !child->hasTagName(theadTag)) - break; - - insertBefore(newFoot, child, ec); + if (!newFoot) + return { }; + return appendChild(*newFoot); } -PassRefPtr<HTMLElement> HTMLTableElement::createTHead() +Ref<HTMLTableSectionElement> HTMLTableElement::createTHead() { - if (HTMLTableSectionElement* existingHead = tHead()) - return existingHead; - RefPtr<HTMLTableSectionElement> head = HTMLTableSectionElement::create(theadTag, document()); - setTHead(head, IGNORE_EXCEPTION); - return head.release(); + if (auto* existingHead = tHead()) + return *existingHead; + auto head = HTMLTableSectionElement::create(theadTag, document()); + setTHead(head.copyRef()); + return head; } void HTMLTableElement::deleteTHead() { - removeChild(tHead(), IGNORE_EXCEPTION); + if (auto* head = tHead()) + removeChild(*head); } -PassRefPtr<HTMLElement> HTMLTableElement::createTFoot() +Ref<HTMLTableSectionElement> HTMLTableElement::createTFoot() { - if (HTMLTableSectionElement* existingFoot = tFoot()) - return existingFoot; - RefPtr<HTMLTableSectionElement> foot = HTMLTableSectionElement::create(tfootTag, document()); - setTFoot(foot, IGNORE_EXCEPTION); - return foot.release(); + if (auto* existingFoot = tFoot()) + return *existingFoot; + auto foot = HTMLTableSectionElement::create(tfootTag, document()); + setTFoot(foot.copyRef()); + return foot; } void HTMLTableElement::deleteTFoot() { - removeChild(tFoot(), IGNORE_EXCEPTION); + if (auto* foot = tFoot()) + removeChild(*foot); } -PassRefPtr<HTMLElement> HTMLTableElement::createTBody() +Ref<HTMLTableSectionElement> HTMLTableElement::createTBody() { - RefPtr<HTMLTableSectionElement> body = HTMLTableSectionElement::create(tbodyTag, document()); - Node* referenceElement = lastBody() ? lastBody()->nextSibling() : 0; - insertBefore(body, referenceElement, ASSERT_NO_EXCEPTION); - return body.release(); + auto body = HTMLTableSectionElement::create(tbodyTag, document()); + Node* referenceElement = lastBody() ? lastBody()->nextSibling() : nullptr; + insertBefore(body, referenceElement); + return body; } -PassRefPtr<HTMLElement> HTMLTableElement::createCaption() +Ref<HTMLTableCaptionElement> HTMLTableElement::createCaption() { - if (HTMLTableCaptionElement* existingCaption = caption()) - return existingCaption; - RefPtr<HTMLTableCaptionElement> caption = HTMLTableCaptionElement::create(captionTag, document()); - setCaption(caption, IGNORE_EXCEPTION); - return caption.release(); + if (auto* existingCaption = caption()) + return *existingCaption; + auto caption = HTMLTableCaptionElement::create(captionTag, document()); + setCaption(caption.copyRef()); + return caption; } void HTMLTableElement::deleteCaption() { - removeChild(caption(), IGNORE_EXCEPTION); + if (auto* caption = this->caption()) + removeChild(*caption); } HTMLTableSectionElement* HTMLTableElement::lastBody() const { for (Node* child = lastChild(); child; child = child->previousSibling()) { if (child->hasTagName(tbodyTag)) - return toHTMLTableSectionElement(child); + return downcast<HTMLTableSectionElement>(child); } - return 0; + return nullptr; } -PassRefPtr<HTMLElement> HTMLTableElement::insertRow(int index, ExceptionCode& ec) +ExceptionOr<Ref<HTMLElement>> HTMLTableElement::insertRow(int index) { - if (index < -1) { - ec = INDEX_SIZE_ERR; - return 0; - } + if (index < -1) + return Exception { INDEX_SIZE_ERR }; - Ref<HTMLTableElement> protectFromMutationEvents(*this); + Ref<HTMLTableElement> protectedThis(*this); - RefPtr<HTMLTableRowElement> lastRow = 0; - RefPtr<HTMLTableRowElement> row = 0; + RefPtr<HTMLTableRowElement> lastRow; + RefPtr<HTMLTableRowElement> row; if (index == -1) - lastRow = HTMLTableRowsCollection::lastRow(this); + lastRow = HTMLTableRowsCollection::lastRow(*this); else { for (int i = 0; i <= index; ++i) { - row = HTMLTableRowsCollection::rowAfter(this, lastRow.get()); + row = HTMLTableRowsCollection::rowAfter(*this, lastRow.get()); if (!row) { - if (i != index) { - ec = INDEX_SIZE_ERR; - return 0; - } + if (i != index) + return Exception { INDEX_SIZE_ERR }; break; } lastRow = row; @@ -216,59 +213,65 @@ PassRefPtr<HTMLElement> HTMLTableElement::insertRow(int index, ExceptionCode& ec else { parent = lastBody(); if (!parent) { - RefPtr<HTMLTableSectionElement> newBody = HTMLTableSectionElement::create(tbodyTag, document()); - RefPtr<HTMLTableRowElement> newRow = HTMLTableRowElement::create(document()); - newBody->appendChild(newRow, ec); - appendChild(newBody.release(), ec); - return newRow.release(); + auto newBody = HTMLTableSectionElement::create(tbodyTag, document()); + auto newRow = HTMLTableRowElement::create(document()); + newBody->appendChild(newRow); + // FIXME: Why ignore the exception if the first appendChild failed? + auto result = appendChild(newBody); + if (result.hasException()) + return result.releaseException(); + return Ref<HTMLElement> { WTFMove(newRow) }; } } - RefPtr<HTMLTableRowElement> newRow = HTMLTableRowElement::create(document()); - parent->insertBefore(newRow, row.get(), ec); - return newRow.release(); + auto newRow = HTMLTableRowElement::create(document()); + auto result = parent->insertBefore(newRow, row.get()); + if (result.hasException()) + return result.releaseException(); + return Ref<HTMLElement> { WTFMove(newRow) }; } -void HTMLTableElement::deleteRow(int index, ExceptionCode& ec) +ExceptionOr<void> HTMLTableElement::deleteRow(int index) { - HTMLTableRowElement* row = 0; - if (index == -1) - row = HTMLTableRowsCollection::lastRow(this); - else { + HTMLTableRowElement* row = nullptr; + if (index == -1) { + row = HTMLTableRowsCollection::lastRow(*this); + if (!row) + return { }; + } else { for (int i = 0; i <= index; ++i) { - row = HTMLTableRowsCollection::rowAfter(this, row); + row = HTMLTableRowsCollection::rowAfter(*this, row); if (!row) break; } + if (!row) + return Exception { INDEX_SIZE_ERR }; } - if (!row) { - ec = INDEX_SIZE_ERR; - return; - } - row->remove(ec); + return row->remove(); } -static inline bool isTableCellAncestor(Node* n) +static inline bool isTableCellAncestor(const Element& element) { - return n->hasTagName(theadTag) || n->hasTagName(tbodyTag) || - n->hasTagName(tfootTag) || n->hasTagName(trTag) || - n->hasTagName(thTag); + return element.hasTagName(theadTag) + || element.hasTagName(tbodyTag) + || element.hasTagName(tfootTag) + || element.hasTagName(trTag) + || element.hasTagName(thTag); } -static bool setTableCellsChanged(Node* n) +static bool setTableCellsChanged(Element& element) { - ASSERT(n); bool cellChanged = false; - if (n->hasTagName(tdTag)) + if (element.hasTagName(tdTag)) cellChanged = true; - else if (isTableCellAncestor(n)) { - for (Node* child = n->firstChild(); child; child = child->nextSibling()) + else if (isTableCellAncestor(element)) { + for (auto& child : childrenOfType<Element>(element)) cellChanged |= setTableCellsChanged(child); } if (cellChanged) - n->setNeedsStyleRecalc(); + element.invalidateStyleForSubtree(); return cellChanged; } @@ -280,21 +283,21 @@ static bool getBordersFromFrameAttributeValue(const AtomicString& value, bool& b borderBottom = false; borderLeft = false; - if (equalIgnoringCase(value, "above")) + if (equalLettersIgnoringASCIICase(value, "above")) borderTop = true; - else if (equalIgnoringCase(value, "below")) + else if (equalLettersIgnoringASCIICase(value, "below")) borderBottom = true; - else if (equalIgnoringCase(value, "hsides")) + else if (equalLettersIgnoringASCIICase(value, "hsides")) borderTop = borderBottom = true; - else if (equalIgnoringCase(value, "vsides")) + else if (equalLettersIgnoringASCIICase(value, "vsides")) borderLeft = borderRight = true; - else if (equalIgnoringCase(value, "lhs")) + else if (equalLettersIgnoringASCIICase(value, "lhs")) borderLeft = true; - else if (equalIgnoringCase(value, "rhs")) + else if (equalLettersIgnoringASCIICase(value, "rhs")) borderRight = true; - else if (equalIgnoringCase(value, "box") || equalIgnoringCase(value, "border")) + else if (equalLettersIgnoringASCIICase(value, "box") || equalLettersIgnoringASCIICase(value, "border")) borderTop = borderBottom = borderLeft = borderRight = true; - else if (!equalIgnoringCase(value, "void")) + else if (!equalLettersIgnoringASCIICase(value, "void")) return false; return true; } @@ -315,7 +318,7 @@ void HTMLTableElement::collectStyleForPresentationAttribute(const QualifiedName& else if (name == backgroundAttr) { String url = stripLeadingAndTrailingHTMLSpaces(value); if (!url.isEmpty()) - style.setProperty(CSSProperty(CSSPropertyBackgroundImage, CSSImageValue::create(document().completeURL(url).string()))); + style.setProperty(CSSProperty(CSSPropertyBackgroundImage, CSSImageValue::create(document().completeURL(url)))); } else if (name == valignAttr) { if (!value.isEmpty()) addPropertyToPresentationAttributeStyle(style, CSSPropertyVerticalAlign, value); @@ -330,7 +333,7 @@ void HTMLTableElement::collectStyleForPresentationAttribute(const QualifiedName& addHTMLLengthToStyle(style, CSSPropertyMarginRight, value); } else if (name == alignAttr) { if (!value.isEmpty()) { - if (equalIgnoringCase(value, "center")) { + if (equalLettersIgnoringASCIICase(value, "center")) { addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitMarginStart, CSSValueAuto); addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitMarginEnd, CSSValueAuto); } else @@ -382,15 +385,15 @@ void HTMLTableElement::parseAttribute(const QualifiedName& name, const AtomicStr m_frameAttr = getBordersFromFrameAttributeValue(value, borderTop, borderRight, borderBottom, borderLeft); } else if (name == rulesAttr) { m_rulesAttr = UnsetRules; - if (equalIgnoringCase(value, "none")) + if (equalLettersIgnoringASCIICase(value, "none")) m_rulesAttr = NoneRules; - else if (equalIgnoringCase(value, "groups")) + else if (equalLettersIgnoringASCIICase(value, "groups")) m_rulesAttr = GroupsRules; - else if (equalIgnoringCase(value, "rows")) + else if (equalLettersIgnoringASCIICase(value, "rows")) m_rulesAttr = RowsRules; - else if (equalIgnoringCase(value, "cols")) + else if (equalLettersIgnoringASCIICase(value, "cols")) m_rulesAttr = ColsRules; - else if (equalIgnoringCase(value, "all")) + else if (equalLettersIgnoringASCIICase(value, "all")) m_rulesAttr = AllRules; } else if (name == cellpaddingAttr) { if (!value.isEmpty()) @@ -403,26 +406,26 @@ void HTMLTableElement::parseAttribute(const QualifiedName& name, const AtomicStr HTMLElement::parseAttribute(name, value); if (bordersBefore != cellBorders() || oldPadding != m_padding) { - m_sharedCellStyle = 0; + m_sharedCellStyle = nullptr; bool cellChanged = false; - for (Node* child = firstChild(); child; child = child->nextSibling()) + for (auto& child : childrenOfType<Element>(*this)) cellChanged |= setTableCellsChanged(child); if (cellChanged) - setNeedsStyleRecalc(); + invalidateStyleForSubtree(); } } static StyleProperties* leakBorderStyle(CSSValueID value) { - RefPtr<MutableStyleProperties> style = MutableStyleProperties::create(); + auto style = MutableStyleProperties::create(); style->setProperty(CSSPropertyBorderTopStyle, value); style->setProperty(CSSPropertyBorderBottomStyle, value); style->setProperty(CSSPropertyBorderLeftStyle, value); style->setProperty(CSSPropertyBorderRightStyle, value); - return style.release().leakRef(); + return &style.leakRef(); } -const StyleProperties* HTMLTableElement::additionalPresentationAttributeStyle() +const StyleProperties* HTMLTableElement::additionalPresentationAttributeStyle() const { if (m_frameAttr) return 0; @@ -468,34 +471,35 @@ HTMLTableElement::CellBorders HTMLTableElement::cellBorders() const return NoBorders; } -PassRefPtr<StyleProperties> HTMLTableElement::createSharedCellStyle() +RefPtr<StyleProperties> HTMLTableElement::createSharedCellStyle() { RefPtr<MutableStyleProperties> style = MutableStyleProperties::create(); + auto& cssValuePool = CSSValuePool::singleton(); switch (cellBorders()) { case SolidBordersColsOnly: style->setProperty(CSSPropertyBorderLeftWidth, CSSValueThin); style->setProperty(CSSPropertyBorderRightWidth, CSSValueThin); style->setProperty(CSSPropertyBorderLeftStyle, CSSValueSolid); style->setProperty(CSSPropertyBorderRightStyle, CSSValueSolid); - style->setProperty(CSSPropertyBorderColor, cssValuePool().createInheritedValue()); + style->setProperty(CSSPropertyBorderColor, cssValuePool.createInheritedValue()); break; case SolidBordersRowsOnly: style->setProperty(CSSPropertyBorderTopWidth, CSSValueThin); style->setProperty(CSSPropertyBorderBottomWidth, CSSValueThin); style->setProperty(CSSPropertyBorderTopStyle, CSSValueSolid); style->setProperty(CSSPropertyBorderBottomStyle, CSSValueSolid); - style->setProperty(CSSPropertyBorderColor, cssValuePool().createInheritedValue()); + style->setProperty(CSSPropertyBorderColor, cssValuePool.createInheritedValue()); break; case SolidBorders: - style->setProperty(CSSPropertyBorderWidth, cssValuePool().createValue(1, CSSPrimitiveValue::CSS_PX)); - style->setProperty(CSSPropertyBorderStyle, cssValuePool().createIdentifierValue(CSSValueSolid)); - style->setProperty(CSSPropertyBorderColor, cssValuePool().createInheritedValue()); + style->setProperty(CSSPropertyBorderWidth, cssValuePool.createValue(1, CSSPrimitiveValue::CSS_PX)); + style->setProperty(CSSPropertyBorderStyle, cssValuePool.createIdentifierValue(CSSValueSolid)); + style->setProperty(CSSPropertyBorderColor, cssValuePool.createInheritedValue()); break; case InsetBorders: - style->setProperty(CSSPropertyBorderWidth, cssValuePool().createValue(1, CSSPrimitiveValue::CSS_PX)); - style->setProperty(CSSPropertyBorderStyle, cssValuePool().createIdentifierValue(CSSValueInset)); - style->setProperty(CSSPropertyBorderColor, cssValuePool().createInheritedValue()); + style->setProperty(CSSPropertyBorderWidth, cssValuePool.createValue(1, CSSPrimitiveValue::CSS_PX)); + style->setProperty(CSSPropertyBorderStyle, cssValuePool.createIdentifierValue(CSSValueInset)); + style->setProperty(CSSPropertyBorderColor, cssValuePool.createInheritedValue()); break; case NoBorders: // If 'rules=none' then allow any borders set at cell level to take effect. @@ -503,9 +507,9 @@ PassRefPtr<StyleProperties> HTMLTableElement::createSharedCellStyle() } if (m_padding) - style->setProperty(CSSPropertyPadding, cssValuePool().createValue(m_padding, CSSPrimitiveValue::CSS_PX)); + style->setProperty(CSSPropertyPadding, cssValuePool.createValue(m_padding, CSSPrimitiveValue::CSS_PX)); - return style.release(); + return style; } const StyleProperties* HTMLTableElement::additionalCellStyle() @@ -517,7 +521,7 @@ const StyleProperties* HTMLTableElement::additionalCellStyle() static StyleProperties* leakGroupBorderStyle(int rows) { - RefPtr<MutableStyleProperties> style = MutableStyleProperties::create(); + auto style = MutableStyleProperties::create(); if (rows) { style->setProperty(CSSPropertyBorderTopWidth, CSSValueThin); style->setProperty(CSSPropertyBorderBottomWidth, CSSValueThin); @@ -529,7 +533,7 @@ static StyleProperties* leakGroupBorderStyle(int rows) style->setProperty(CSSPropertyBorderLeftStyle, CSSValueSolid); style->setProperty(CSSPropertyBorderRightStyle, CSSValueSolid); } - return style.release().leakRef(); + return &style.leakRef(); } const StyleProperties* HTMLTableElement::additionalGroupStyle(bool rows) @@ -550,31 +554,31 @@ bool HTMLTableElement::isURLAttribute(const Attribute& attribute) const return attribute.name() == backgroundAttr || HTMLElement::isURLAttribute(attribute); } -PassRefPtr<HTMLCollection> HTMLTableElement::rows() +Ref<HTMLCollection> HTMLTableElement::rows() { - return ensureCachedHTMLCollection(TableRows); + return ensureRareData().ensureNodeLists().addCachedCollection<HTMLTableRowsCollection>(*this, TableRows); } -PassRefPtr<HTMLCollection> HTMLTableElement::tBodies() +Ref<HTMLCollection> HTMLTableElement::tBodies() { - return ensureCachedHTMLCollection(TableTBodies); + return ensureRareData().ensureNodeLists().addCachedCollection<GenericCachedHTMLCollection<CollectionTypeTraits<TableTBodies>::traversalType>>(*this, TableTBodies); } -String HTMLTableElement::rules() const +const AtomicString& HTMLTableElement::rules() const { - return getAttribute(rulesAttr); + return attributeWithoutSynchronization(rulesAttr); } -String HTMLTableElement::summary() const +const AtomicString& HTMLTableElement::summary() const { - return getAttribute(summaryAttr); + return attributeWithoutSynchronization(summaryAttr); } void HTMLTableElement::addSubresourceAttributeURLs(ListHashSet<URL>& urls) const { HTMLElement::addSubresourceAttributeURLs(urls); - addSubresourceURL(urls, document().completeURL(getAttribute(backgroundAttr))); + addSubresourceURL(urls, document().completeURL(attributeWithoutSynchronization(backgroundAttr))); } } |