diff options
Diffstat (limited to 'Source/WebCore/dom/Text.cpp')
-rw-r--r-- | Source/WebCore/dom/Text.cpp | 148 |
1 files changed, 77 insertions, 71 deletions
diff --git a/Source/WebCore/dom/Text.cpp b/Source/WebCore/dom/Text.cpp index ec140b0af..45f8e27f6 100644 --- a/Source/WebCore/dom/Text.cpp +++ b/Source/WebCore/dom/Text.cpp @@ -22,84 +22,73 @@ #include "config.h" #include "Text.h" +#include "Event.h" +#include "ExceptionCode.h" #include "RenderCombineText.h" +#include "RenderSVGInlineText.h" #include "RenderText.h" +#include "RenderTreeUpdater.h" +#include "SVGElement.h" +#include "SVGNames.h" #include "ScopedEventQueue.h" #include "ShadowRoot.h" -#include "TextNodeTraversal.h" - -#if ENABLE(SVG) -#include "RenderSVGInlineText.h" -#include "SVGNames.h" -#endif - #include "StyleInheritedData.h" #include "StyleResolver.h" +#include "StyleUpdate.h" +#include "TextNodeTraversal.h" #include <wtf/CheckedArithmetic.h> #include <wtf/text/CString.h> #include <wtf/text/StringBuilder.h> namespace WebCore { -PassRefPtr<Text> Text::create(Document& document, const String& data) -{ - return adoptRef(new Text(document, data, CreateText)); -} - -PassRefPtr<Text> Text::create(ScriptExecutionContext& context, const String& data) +Ref<Text> Text::create(Document& document, const String& data) { - return adoptRef(new Text(toDocument(context), data, CreateText)); + return adoptRef(*new Text(document, data, CreateText)); } -PassRefPtr<Text> Text::createEditingText(Document& document, const String& data) +Ref<Text> Text::createEditingText(Document& document, const String& data) { - return adoptRef(new Text(document, data, CreateEditingText)); + return adoptRef(*new Text(document, data, CreateEditingText)); } Text::~Text() { - ASSERT(!renderer()); } -PassRefPtr<Text> Text::splitText(unsigned offset, ExceptionCode& ec) +ExceptionOr<Ref<Text>> Text::splitText(unsigned offset) { - 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 0; - } + if (offset > length()) + return Exception { INDEX_SIZE_ERR }; EventQueueScope scope; - String oldStr = data(); - RefPtr<Text> newText = virtualCreate(oldStr.substring(offset)); - setDataWithoutUpdate(oldStr.substring(0, offset)); + auto oldData = data(); + auto newText = virtualCreate(oldData.substring(offset)); + setDataWithoutUpdate(oldData.substring(0, offset)); - dispatchModifiedEvent(oldStr); + dispatchModifiedEvent(oldData); - if (parentNode()) - parentNode()->insertBefore(newText.get(), nextSibling(), ec); - if (ec) - return 0; + if (auto* parent = parentNode()) { + auto insertResult = parent->insertBefore(newText, nextSibling()); + if (insertResult.hasException()) + return insertResult.releaseException(); + } - if (parentNode()) - document().textNodeSplit(this); + document().textNodeSplit(this); if (renderer()) - renderer()->setTextWithOffset(dataImpl(), 0, oldStr.length()); + renderer()->setTextWithOffset(data(), 0, oldData.length()); - return newText.release(); + return WTFMove(newText); } static const Text* earliestLogicallyAdjacentTextNode(const Text* text) { const Node* node = text; while ((node = node->previousSibling())) { - if (!node->isTextNode()) + if (!is<Text>(*node)) break; - text = toText(node); + text = downcast<Text>(node); } return text; } @@ -108,9 +97,9 @@ static const Text* latestLogicallyAdjacentTextNode(const Text* text) { const Node* node = text; while ((node = node->nextSibling())) { - if (!node->isTextNode()) + if (!is<Text>(*node)) break; - text = toText(node); + text = downcast<Text>(node); } return text; } @@ -119,15 +108,16 @@ String Text::wholeText() const { const Text* startText = earliestLogicallyAdjacentTextNode(this); const Text* endText = latestLogicallyAdjacentTextNode(this); - const Node* onePastEndText = TextNodeTraversal::nextSibling(endText); + ASSERT(endText); + const Node* onePastEndText = TextNodeTraversal::nextSibling(*endText); StringBuilder result; - for (const Text* text = startText; text != onePastEndText; text = TextNodeTraversal::nextSibling(text)) + for (const Text* text = startText; text != onePastEndText; text = TextNodeTraversal::nextSibling(*text)) result.append(text->data()); return result.toString(); } -PassRefPtr<Text> Text::replaceWholeText(const String& newText, ExceptionCode&) +RefPtr<Text> Text::replaceWholeText(const String& newText) { // Remove all adjacent text nodes, and replace the contents of this one. @@ -138,33 +128,33 @@ PassRefPtr<Text> Text::replaceWholeText(const String& newText, ExceptionCode&) RefPtr<Text> protectedThis(this); // Mutation event handlers could cause our last ref to go away RefPtr<ContainerNode> parent = parentNode(); // Protect against mutation handlers moving this node during traversal for (RefPtr<Node> n = startText; n && n != this && n->isTextNode() && n->parentNode() == parent;) { - RefPtr<Node> nodeToRemove(n.release()); + Ref<Node> nodeToRemove(n.releaseNonNull()); n = nodeToRemove->nextSibling(); - parent->removeChild(nodeToRemove.get(), IGNORE_EXCEPTION); + parent->removeChild(nodeToRemove); } if (this != endText) { Node* onePastEndText = endText->nextSibling(); for (RefPtr<Node> n = nextSibling(); n && n != onePastEndText && n->isTextNode() && n->parentNode() == parent;) { - RefPtr<Node> nodeToRemove(n.release()); + Ref<Node> nodeToRemove(n.releaseNonNull()); n = nodeToRemove->nextSibling(); - parent->removeChild(nodeToRemove.get(), IGNORE_EXCEPTION); + parent->removeChild(nodeToRemove); } } if (newText.isEmpty()) { if (parent && parentNode() == parent) - parent->removeChild(this, IGNORE_EXCEPTION); - return 0; + parent->removeChild(*this); + return nullptr; } - setData(newText, IGNORE_EXCEPTION); - return protectedThis.release(); + setData(newText); + return protectedThis; } String Text::nodeName() const { - return textAtom.string(); + return ASCIILiteral("#text"); } Node::NodeType Text::nodeType() const @@ -172,17 +162,16 @@ Node::NodeType Text::nodeType() const return TEXT_NODE; } -PassRefPtr<Node> Text::cloneNode(bool /*deep*/) +Ref<Node> Text::cloneNodeInternal(Document& targetDocument, CloningOperation) { - return create(document(), data()); + return create(targetDocument, data()); } - -#if ENABLE(SVG) static bool isSVGShadowText(Text* text) { Node* parentNode = text->parentNode(); - return parentNode->isShadowRoot() && toShadowRoot(parentNode)->hostElement()->hasTagName(SVGNames::trefTag); + ASSERT(parentNode); + return is<ShadowRoot>(*parentNode) && downcast<ShadowRoot>(*parentNode).host()->hasTagName(SVGNames::trefTag); } static bool isSVGText(Text* text) @@ -190,18 +179,16 @@ static bool isSVGText(Text* text) Node* parentOrShadowHostNode = text->parentOrShadowHostNode(); return parentOrShadowHostNode->isSVGElement() && !parentOrShadowHostNode->hasTagName(SVGNames::foreignObjectTag); } -#endif RenderPtr<RenderText> Text::createTextRenderer(const RenderStyle& style) { -#if ENABLE(SVG) if (isSVGText(this) || isSVGShadowText(this)) - return createRenderer<RenderSVGInlineText>(*this, dataImpl()); -#endif + return createRenderer<RenderSVGInlineText>(*this, data()); + if (style.hasTextCombine()) - return createRenderer<RenderCombineText>(*this, dataImpl()); + return createRenderer<RenderCombineText>(*this, data()); - return createRenderer<RenderText>(*this, dataImpl()); + return createRenderer<RenderText>(*this, data()); } bool Text::childTypeAllowed(NodeType) const @@ -209,25 +196,40 @@ bool Text::childTypeAllowed(NodeType) const return false; } -PassRefPtr<Text> Text::virtualCreate(const String& data) +Ref<Text> Text::virtualCreate(const String& data) { return create(document(), data); } -PassRefPtr<Text> Text::createWithLengthLimit(Document& document, const String& data, unsigned start, unsigned lengthLimit) +Ref<Text> Text::createWithLengthLimit(Document& document, const String& data, unsigned start, unsigned lengthLimit) { unsigned dataLength = data.length(); if (!start && dataLength <= lengthLimit) return create(document, data); - RefPtr<Text> result = Text::create(document, String()); + Ref<Text> result = Text::create(document, String()); result->parserAppendData(data, start, lengthLimit); - return result; } -#ifndef NDEBUG +void Text::updateRendererAfterContentChange(unsigned offsetOfReplacedData, unsigned lengthOfReplacedData) +{ + ASSERT(parentNode()); + if (styleValidity() >= Style::Validity::SubtreeAndRenderersInvalid) + return; + + auto textUpdate = std::make_unique<Style::Update>(document()); + textUpdate->addText(*this); + + RenderTreeUpdater renderTreeUpdater(document()); + renderTreeUpdater.commit(WTFMove(textUpdate)); + + if (auto* renderer = this->renderer()) + renderer->setTextWithOffset(data(), offsetOfReplacedData, lengthOfReplacedData); +} + +#if ENABLE(TREE_DEBUGGING) void Text::formatForDebugger(char* buffer, unsigned length) const { StringBuilder result; @@ -239,11 +241,15 @@ void Text::formatForDebugger(char* buffer, unsigned length) const if (s.length() > 0) { if (result.length()) result.appendLiteral("; "); - result.appendLiteral("value="); + result.appendLiteral("length="); + result.appendNumber(s.length()); + result.appendLiteral("; value=\""); result.append(s); + result.append('"'); } strncpy(buffer, result.toString().utf8().data(), length - 1); + buffer[length - 1] = '\0'; } #endif |