diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/dom/CharacterData.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/dom/CharacterData.cpp')
-rw-r--r-- | Source/WebCore/dom/CharacterData.cpp | 178 |
1 files changed, 91 insertions, 87 deletions
diff --git a/Source/WebCore/dom/CharacterData.cpp b/Source/WebCore/dom/CharacterData.cpp index 7ac273f62..4e564bce2 100644 --- a/Source/WebCore/dom/CharacterData.cpp +++ b/Source/WebCore/dom/CharacterData.cpp @@ -22,40 +22,53 @@ #include "config.h" #include "CharacterData.h" +#include "Attr.h" #include "ElementTraversal.h" +#include "EventNames.h" #include "ExceptionCode.h" #include "FrameSelection.h" #include "InspectorInstrumentation.h" #include "MutationEvent.h" #include "MutationObserverInterestGroup.h" #include "MutationRecord.h" +#include "NoEventDispatchAssertion.h" #include "ProcessingInstruction.h" #include "RenderText.h" #include "StyleInheritedData.h" -#include "TextBreakIterator.h" +#include <unicode/ubrk.h> #include <wtf/Ref.h> namespace WebCore { -void CharacterData::setData(const String& data, ExceptionCode&) +static bool canUseSetDataOptimization(const CharacterData& node) +{ + auto& document = node.document(); + return !document.hasListenerType(Document::DOMCHARACTERDATAMODIFIED_LISTENER) && !document.hasMutationObserversOfType(MutationObserver::CharacterData) + && !document.hasListenerType(Document::DOMSUBTREEMODIFIED_LISTENER); +} + +void CharacterData::setData(const String& data) { const String& nonNullData = !data.isNull() ? data : emptyString(); - if (m_data == nonNullData) - return; + unsigned oldLength = length(); - Ref<CharacterData> protect(*this); + if (m_data == nonNullData && canUseSetDataOptimization(*this)) { + document().textRemoved(this, 0, oldLength); + if (document().frame()) + document().frame()->selection().textWasReplaced(this, 0, oldLength, oldLength); + return; + } - unsigned oldLength = length(); + Ref<CharacterData> protectedThis(*this); setDataAndUpdate(nonNullData, 0, oldLength, nonNullData.length()); document().textRemoved(this, 0, oldLength); } -String CharacterData::substringData(unsigned offset, unsigned count, ExceptionCode& ec) +ExceptionOr<String> CharacterData::substringData(unsigned offset, unsigned count) { - checkCharDataOperation(offset, ec); - if (ec) - return String(); + if (offset > length()) + return Exception { INDEX_SIZE_ERR }; return m_data.substring(offset, count); } @@ -75,8 +88,8 @@ unsigned CharacterData::parserAppendData(const String& string, unsigned offset, // We need at least two characters look-ahead to account for UTF-16 surrogates. if (characterLengthLimit < characterLength) { NonSharedCharacterBreakIterator it(StringView(string).substring(offset, (characterLengthLimit + 2 > characterLength) ? characterLength : characterLengthLimit + 2)); - if (!isTextBreak(it, characterLengthLimit)) - characterLengthLimit = textBreakPreceding(it, characterLengthLimit); + if (!ubrk_isBoundary(it, characterLengthLimit)) + characterLengthLimit = ubrk_preceding(it, characterLengthLimit); } if (!characterLengthLimit) @@ -87,27 +100,16 @@ unsigned CharacterData::parserAppendData(const String& string, unsigned offset, else m_data.append(string.characters16() + offset, characterLengthLimit); - ASSERT(!renderer() || isTextNode()); - if (isTextNode()) - Style::updateTextRendererAfterContentChange(*toText(this), oldLength, 0); + ASSERT(!renderer() || is<Text>(*this)); + if (is<Text>(*this) && parentNode()) + downcast<Text>(*this).updateRendererAfterContentChange(oldLength, 0); - document().incDOMTreeVersion(); - // We don't call dispatchModifiedEvent here because we don't want the - // parser to dispatch DOM mutation events. - if (parentNode()) { - ContainerNode::ChildChange change = { - ContainerNode::TextChanged, - ElementTraversal::previousSibling(this), - ElementTraversal::nextSibling(this), - ContainerNode::ChildChangeSourceParser - }; - parentNode()->childrenChanged(change); - } + notifyParentAfterChange(ContainerNode::ChildChangeSourceParser); return characterLengthLimit; } -void CharacterData::appendData(const String& data, ExceptionCode&) +void CharacterData::appendData(const String& data) { String newStr = m_data; newStr.append(data); @@ -117,11 +119,10 @@ void CharacterData::appendData(const String& data, ExceptionCode&) // FIXME: Should we call textInserted here? } -void CharacterData::insertData(unsigned offset, const String& data, ExceptionCode& ec) +ExceptionOr<void> CharacterData::insertData(unsigned offset, const String& data) { - checkCharDataOperation(offset, ec); - if (ec) - return; + if (offset > length()) + return Exception { INDEX_SIZE_ERR }; String newStr = m_data; newStr.insert(data, offset); @@ -129,49 +130,45 @@ void CharacterData::insertData(unsigned offset, const String& data, ExceptionCod setDataAndUpdate(newStr, offset, 0, data.length()); document().textInserted(this, offset, data.length()); + + return { }; } -void CharacterData::deleteData(unsigned offset, unsigned count, ExceptionCode& ec) +ExceptionOr<void> CharacterData::deleteData(unsigned offset, unsigned count) { - checkCharDataOperation(offset, ec); - if (ec) - return; + if (offset > length()) + return Exception { INDEX_SIZE_ERR }; - unsigned realCount; - if (offset + count > length()) - realCount = length() - offset; - else - realCount = count; + count = std::min(count, length() - offset); String newStr = m_data; - newStr.remove(offset, realCount); + newStr.remove(offset, count); setDataAndUpdate(newStr, offset, count, 0); - document().textRemoved(this, offset, realCount); + document().textRemoved(this, offset, count); + + return { }; } -void CharacterData::replaceData(unsigned offset, unsigned count, const String& data, ExceptionCode& ec) +ExceptionOr<void> CharacterData::replaceData(unsigned offset, unsigned count, const String& data) { - checkCharDataOperation(offset, ec); - if (ec) - return; + if (offset > length()) + return Exception { INDEX_SIZE_ERR }; - unsigned realCount; - if (offset + count > length()) - realCount = length() - offset; - else - realCount = count; + count = std::min(count, length() - offset); String newStr = m_data; - newStr.remove(offset, realCount); + newStr.remove(offset, count); newStr.insert(data, offset); setDataAndUpdate(newStr, offset, count, data.length()); // update the markers for spell checking and grammar checking - document().textRemoved(this, offset, realCount); + document().textRemoved(this, offset, count); document().textInserted(this, offset, data.length()); + + return { }; } String CharacterData::nodeValue() const @@ -184,9 +181,10 @@ bool CharacterData::containsOnlyWhitespace() const return m_data.containsOnlyWhitespace(); } -void CharacterData::setNodeValue(const String& nodeValue, ExceptionCode& ec) +ExceptionOr<void> CharacterData::setNodeValue(const String& nodeValue) { - setData(nodeValue, ec); + setData(nodeValue); + return { }; } void CharacterData::setDataAndUpdate(const String& newData, unsigned offsetOfReplacedData, unsigned oldLength, unsigned newLength) @@ -194,54 +192,60 @@ void CharacterData::setDataAndUpdate(const String& newData, unsigned offsetOfRep String oldData = m_data; m_data = newData; - ASSERT(!renderer() || isTextNode()); - if (isTextNode()) - Style::updateTextRendererAfterContentChange(*toText(this), offsetOfReplacedData, oldLength); + ASSERT(!renderer() || is<Text>(*this)); + if (is<Text>(*this) && parentNode()) + downcast<Text>(*this).updateRendererAfterContentChange(offsetOfReplacedData, oldLength); - if (nodeType() == PROCESSING_INSTRUCTION_NODE) - toProcessingInstruction(this)->checkStyleSheet(); + if (is<ProcessingInstruction>(*this)) + downcast<ProcessingInstruction>(*this).checkStyleSheet(); if (document().frame()) document().frame()->selection().textWasReplaced(this, offsetOfReplacedData, oldLength, newLength); - document().incDOMTreeVersion(); + notifyParentAfterChange(ContainerNode::ChildChangeSourceAPI); + dispatchModifiedEvent(oldData); } +void CharacterData::notifyParentAfterChange(ContainerNode::ChildChangeSource source) +{ +#if !ASSERT_DISABLED + auto assertNoEventDispatch = std::make_unique<NoEventDispatchAssertion>(); +#endif + + document().incDOMTreeVersion(); + + if (!parentNode()) + return; + + ContainerNode::ChildChange change = { + ContainerNode::TextChanged, + ElementTraversal::previousSibling(*this), + ElementTraversal::nextSibling(*this), + source + }; + +#if !ASSERT_DISABLED + // Attribute CharacterData is expected to fire events. + if (is<Attr>(*parentNode())) + assertNoEventDispatch = nullptr; +#endif + + parentNode()->childrenChanged(change); +} + void CharacterData::dispatchModifiedEvent(const String& oldData) { - if (OwnPtr<MutationObserverInterestGroup> mutationRecipients = MutationObserverInterestGroup::createForCharacterDataMutation(*this)) + if (auto mutationRecipients = MutationObserverInterestGroup::createForCharacterDataMutation(*this)) mutationRecipients->enqueueMutationRecord(MutationRecord::createCharacterData(*this, oldData)); if (!isInShadowTree()) { - if (parentNode()) { - ContainerNode::ChildChange change = { - ContainerNode::TextChanged, - ElementTraversal::previousSibling(this), - ElementTraversal::nextSibling(this), - ContainerNode::ChildChangeSourceAPI - }; - parentNode()->childrenChanged(change); - } if (document().hasListenerType(Document::DOMCHARACTERDATAMODIFIED_LISTENER)) - dispatchScopedEvent(MutationEvent::create(eventNames().DOMCharacterDataModifiedEvent, true, 0, oldData, m_data)); + dispatchScopedEvent(MutationEvent::create(eventNames().DOMCharacterDataModifiedEvent, true, nullptr, oldData, m_data)); dispatchSubtreeModifiedEvent(); } -#if ENABLE(INSPECTOR) - InspectorInstrumentation::characterDataModified(&document(), this); -#endif -} -void CharacterData::checkCharDataOperation(unsigned offset, ExceptionCode& ec) -{ - ec = 0; - - // INDEX_SIZE_ERR: Raised if the specified offset is negative or greater than the number of 16-bit - // units in data. - if (offset > length()) { - ec = INDEX_SIZE_ERR; - return; - } + InspectorInstrumentation::characterDataModified(document(), *this); } int CharacterData::maxCharacterOffset() const |