Bug 1406482 - Avoid using nsINode::GetChildAt() in EditorBase::InsertTextImpl(); r=masayuki

This commit is contained in:
Ehsan Akhgari 2017-10-06 14:02:40 -04:00
parent 9186f2dee6
commit 1bba75e15f
9 changed files with 68 additions and 17 deletions

View File

@ -2391,13 +2391,14 @@ EditorBase::FindBetterInsertionPoint(nsCOMPtr<nsIDOMNode>& aNode,
int32_t& aOffset)
{
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
FindBetterInsertionPoint(node, aOffset);
FindBetterInsertionPoint(node, aOffset, nullptr);
aNode = do_QueryInterface(node);
}
void
EditorBase::FindBetterInsertionPoint(nsCOMPtr<nsINode>& aNode,
int32_t& aOffset)
int32_t& aOffset,
nsCOMPtr<nsIContent>* aSelChild)
{
if (aNode->IsNodeOfType(nsINode::eTEXT)) {
// There is no "better" insertion point.
@ -2424,6 +2425,9 @@ EditorBase::FindBetterInsertionPoint(nsCOMPtr<nsINode>& aNode,
node->GetFirstChild()->IsNodeOfType(nsINode::eTEXT)) {
aNode = node->GetFirstChild();
aOffset = 0;
if (aSelChild) {
*aSelChild = nullptr;
}
return;
}
@ -2439,6 +2443,9 @@ EditorBase::FindBetterInsertionPoint(nsCOMPtr<nsINode>& aNode,
NS_ENSURE_TRUE_VOID(node->Length() <= INT32_MAX);
aNode = child;
aOffset = static_cast<int32_t>(aNode->Length());
if (aSelChild) {
*aSelChild = nullptr;
}
return;
}
} else {
@ -2450,6 +2457,9 @@ EditorBase::FindBetterInsertionPoint(nsCOMPtr<nsINode>& aNode,
NS_ENSURE_TRUE_VOID(node->Length() <= INT32_MAX);
aNode = child;
aOffset = static_cast<int32_t>(aNode->Length());
if (aSelChild) {
*aSelChild = nullptr;
}
return;
}
child = child->GetPreviousSibling();
@ -2467,10 +2477,16 @@ EditorBase::FindBetterInsertionPoint(nsCOMPtr<nsINode>& aNode,
NS_ENSURE_TRUE_VOID(node->Length() <= INT32_MAX);
aNode = node->GetPreviousSibling();
aOffset = static_cast<int32_t>(aNode->Length());
if (aSelChild) {
*aSelChild = nullptr;
}
return;
}
if (node->GetParentNode() && node->GetParentNode() == root) {
if (aSelChild) {
*aSelChild = node->AsContent();
}
aNode = node->GetParentNode();
aOffset = 0;
return;
@ -2481,6 +2497,7 @@ EditorBase::FindBetterInsertionPoint(nsCOMPtr<nsINode>& aNode,
nsresult
EditorBase::InsertTextImpl(const nsAString& aStringToInsert,
nsCOMPtr<nsINode>* aInOutNode,
nsCOMPtr<nsIContent>* aInOutChildAtOffset,
int32_t* aInOutOffset,
nsIDocument* aDoc)
{
@ -2502,15 +2519,17 @@ EditorBase::InsertTextImpl(const nsAString& aStringToInsert,
nsCOMPtr<nsINode> node = *aInOutNode;
int32_t offset = *aInOutOffset;
nsCOMPtr<nsIContent> child = *aInOutChildAtOffset;
MOZ_ASSERT(node->GetChildAt(offset) == *aInOutChildAtOffset);
// In some cases, the node may be the anonymous div elemnt or a mozBR
// element. Let's try to look for better insertion point in the nearest
// text node if there is.
FindBetterInsertionPoint(node, offset);
FindBetterInsertionPoint(node, offset, address_of(child));
// If a neighboring text node already exists, use that
if (!node->IsNodeOfType(nsINode::eTEXT)) {
nsIContent* child = node->GetChildAt(offset);
if (offset && child && child->GetPreviousSibling() &&
child->GetPreviousSibling()->IsNodeOfType(nsINode::eTEXT)) {
node = child->GetPreviousSibling();
@ -2566,6 +2585,7 @@ EditorBase::InsertTextImpl(const nsAString& aStringToInsert,
*aInOutNode = node;
*aInOutOffset = offset;
*aInOutChildAtOffset = nullptr;
return NS_OK;
}
@ -4966,7 +4986,7 @@ EditorBase::InitializeSelection(nsIDOMEventTarget* aFocusEventTarget)
NS_ENSURE_TRUE(firstRange, NS_ERROR_FAILURE);
nsCOMPtr<nsINode> startNode = firstRange->GetStartContainer();
int32_t startOffset = firstRange->StartOffset();
FindBetterInsertionPoint(startNode, startOffset);
FindBetterInsertionPoint(startNode, startOffset, nullptr);
Text* textNode = startNode->GetAsText();
MOZ_ASSERT(textNode,
"There must be text node if mIMETextLength is larger than 0");

View File

@ -287,6 +287,7 @@ public:
virtual nsresult InsertTextImpl(const nsAString& aStringToInsert,
nsCOMPtr<nsINode>* aInOutNode,
nsCOMPtr<nsIContent>* aInOutChildAtOffset,
int32_t* aInOutOffset,
nsIDocument* aDoc);
nsresult InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
@ -1222,11 +1223,23 @@ public:
/**
* FindBetterInsertionPoint() tries to look for better insertion point which
* is typically the nearest text node and offset in it.
*
* @param aNode in/out param, on input set to the node to use to start the search,
* on output set to the node found as the better insertion point.
* @param aOffset in/out param, on input set to the offset to use to start the
* search, on putput set to the offset found as the better insertion
* point.
* @param aSelChild in/out param, on input, can be set to nullptr if the caller
* doesn't want to pass this in, or set to a pointer to an nsCOMPtr
* pointing to the child at the input node and offset, and on output
* the method will make it point to the child at the output node and
* offset returned in aNode and aOffset.
*/
void FindBetterInsertionPoint(nsCOMPtr<nsIDOMNode>& aNode,
int32_t& aOffset);
void FindBetterInsertionPoint(nsCOMPtr<nsINode>& aNode,
int32_t& aOffset);
int32_t& aOffset,
nsCOMPtr<nsIContent>* aSelChild);
/**
* HideCaret() hides caret with nsCaret::AddForceHide() or may show carent

View File

@ -1299,6 +1299,8 @@ HTMLEditRules::WillInsertText(EditAction aAction,
NS_ENSURE_STATE(mHTMLEditor);
NS_ENSURE_STATE(aSelection->GetRangeAt(0));
nsCOMPtr<nsINode> selNode = aSelection->GetRangeAt(0)->GetStartContainer();
nsCOMPtr<nsIContent> selChild =
aSelection->GetRangeAt(0)->GetChildAtStartOffset();
int32_t selOffset = aSelection->GetRangeAt(0)->StartOffset();
NS_ENSURE_STATE(selNode);
@ -1323,13 +1325,15 @@ HTMLEditRules::WillInsertText(EditAction aAction,
}
if (inString->IsEmpty()) {
rv = mHTMLEditor->InsertTextImpl(*inString, address_of(selNode),
address_of(selChild),
&selOffset, doc);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
} else {
WSRunObject wsObj(mHTMLEditor, selNode, selOffset);
rv = wsObj.InsertText(*inString, address_of(selNode), &selOffset, doc);
rv = wsObj.InsertText(*inString, address_of(selNode),
address_of(selChild), &selOffset, doc);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -1401,6 +1405,7 @@ HTMLEditRules::WillInsertText(EditAction aAction,
} else {
NS_ENSURE_STATE(mHTMLEditor);
rv = mHTMLEditor->InsertTextImpl(subStr, address_of(curNode),
address_of(selChild),
&curOffset, doc);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -1433,7 +1438,8 @@ HTMLEditRules::WillInsertText(EditAction aAction,
// is it a tab?
if (subStr.Equals(tabStr)) {
rv =
wsObj.InsertText(spacesStr, address_of(curNode), &curOffset, doc);
wsObj.InsertText(spacesStr, address_of(curNode),
address_of(selChild), &curOffset, doc);
NS_ENSURE_SUCCESS(rv, rv);
pos++;
}
@ -1444,8 +1450,10 @@ HTMLEditRules::WillInsertText(EditAction aAction,
nsIEditor::eNone);
NS_ENSURE_TRUE(br, NS_ERROR_FAILURE);
pos++;
selChild = br->GetNextSibling();;
} else {
rv = wsObj.InsertText(subStr, address_of(curNode), &curOffset, doc);
rv = wsObj.InsertText(subStr, address_of(curNode),
address_of(selChild), &curOffset, doc);
NS_ENSURE_SUCCESS(rv, rv);
}
}

View File

@ -3118,6 +3118,7 @@ HTMLEditor::DeleteText(nsGenericDOMDataNode& aCharData,
nsresult
HTMLEditor::InsertTextImpl(const nsAString& aStringToInsert,
nsCOMPtr<nsINode>* aInOutNode,
nsCOMPtr<nsIContent>* aInOutChildAtOffset,
int32_t* aInOutOffset,
nsIDocument* aDoc)
{
@ -3126,8 +3127,9 @@ HTMLEditor::InsertTextImpl(const nsAString& aStringToInsert,
return NS_ERROR_FAILURE;
}
return EditorBase::InsertTextImpl(aStringToInsert, aInOutNode, aInOutOffset,
aDoc);
return EditorBase::InsertTextImpl(aStringToInsert, aInOutNode,
aInOutChildAtOffset,
aInOutOffset, aDoc);
}
void

View File

@ -313,6 +313,7 @@ public:
uint32_t aLength);
virtual nsresult InsertTextImpl(const nsAString& aStringToInsert,
nsCOMPtr<nsINode>* aInOutNode,
nsCOMPtr<nsIContent>* aInOutChildAtOffset,
int32_t* aInOutOffset,
nsIDocument* aDoc) override;
NS_IMETHOD_(bool) IsModifiableNode(nsIDOMNode* aNode) override;

View File

@ -726,6 +726,8 @@ TextEditRules::WillInsertText(EditAction aAction,
// get the (collapsed) selection location
NS_ENSURE_STATE(aSelection->GetRangeAt(0));
nsCOMPtr<nsINode> selNode = aSelection->GetRangeAt(0)->GetStartContainer();
nsCOMPtr<nsIContent> selChild =
aSelection->GetRangeAt(0)->GetChildAtStartOffset();
int32_t selOffset = aSelection->GetRangeAt(0)->StartOffset();
NS_ENSURE_STATE(selNode);
@ -744,7 +746,8 @@ TextEditRules::WillInsertText(EditAction aAction,
if (aAction == EditAction::insertIMEText) {
NS_ENSURE_STATE(mTextEditor);
// Find better insertion point to insert text.
mTextEditor->FindBetterInsertionPoint(selNode, selOffset);
mTextEditor->FindBetterInsertionPoint(selNode, selOffset,
address_of(selChild));
// If there is one or more IME selections, its minimum offset should be
// the insertion point.
int32_t IMESelectionOffset =
@ -753,7 +756,7 @@ TextEditRules::WillInsertText(EditAction aAction,
selOffset = IMESelectionOffset;
}
rv = mTextEditor->InsertTextImpl(*outString, address_of(selNode),
&selOffset, doc);
address_of(selChild), &selOffset, doc);
NS_ENSURE_SUCCESS(rv, rv);
} else {
// aAction == EditAction::insertText; find where we are
@ -765,7 +768,7 @@ TextEditRules::WillInsertText(EditAction aAction,
AutoTransactionsConserveSelection dontChangeMySelection(mTextEditor);
rv = mTextEditor->InsertTextImpl(*outString, address_of(curNode),
&curOffset, doc);
address_of(selChild), &curOffset, doc);
NS_ENSURE_SUCCESS(rv, rv);
if (curNode) {

View File

@ -551,7 +551,7 @@ TextEditor::ExtendSelectionForDelete(Selection* aSelection,
NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
// node might be anonymous DIV, so we find better text node
FindBetterInsertionPoint(node, offset);
FindBetterInsertionPoint(node, offset, nullptr);
if (IsTextNode(node)) {
const nsTextFragment* data = node->GetAsText()->GetText();
@ -704,6 +704,7 @@ TextEditor::InsertLineBreak()
// get the (collapsed) selection location
NS_ENSURE_STATE(selection->GetRangeAt(0));
nsCOMPtr<nsINode> selNode = selection->GetRangeAt(0)->GetStartContainer();
nsCOMPtr<nsIContent> selChild = selection->GetRangeAt(0)->GetChildAtStartOffset();
int32_t selOffset = selection->GetRangeAt(0)->StartOffset();
NS_ENSURE_STATE(selNode);
@ -722,7 +723,7 @@ TextEditor::InsertLineBreak()
// insert a linefeed character
rv = InsertTextImpl(NS_LITERAL_STRING("\n"), address_of(selNode),
&selOffset, doc);
address_of(selChild), &selOffset, doc);
if (!selNode) {
rv = NS_ERROR_NULL_POINTER; // don't return here, so DidDoAction is called
}

View File

@ -234,6 +234,7 @@ WSRunObject::InsertBreak(nsCOMPtr<nsINode>* aInOutParent,
nsresult
WSRunObject::InsertText(const nsAString& aStringToInsert,
nsCOMPtr<nsINode>* aInOutParent,
nsCOMPtr<nsIContent>* aInOutChildAtOffset,
int32_t* aInOutOffset,
nsIDocument* aDoc)
{
@ -356,7 +357,8 @@ WSRunObject::InsertText(const nsAString& aStringToInsert,
}
// Ready, aim, fire!
mHTMLEditor->InsertTextImpl(theString, aInOutParent, aInOutOffset, aDoc);
mHTMLEditor->InsertTextImpl(theString, aInOutParent, aInOutChildAtOffset,
aInOutOffset, aDoc);
return NS_OK;
}

View File

@ -224,6 +224,7 @@ public:
// trailingws before {aInOutParent,aInOutOffset} needs to be removed.
nsresult InsertText(const nsAString& aStringToInsert,
nsCOMPtr<nsINode>* aInOutNode,
nsCOMPtr<nsIContent>* aInOutChildAtOffset,
int32_t* aInOutOffset,
nsIDocument* aDoc);