mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Bug 1533293 - part 2: Rewrite EditorBase::SelectEntireDocument() and its overrides r=m_kato
`EditorBase::SelectEntierDocument()` uses `Selection::Extend()` but it's too slow. It should use `Selection::SetStartAndEndInLimiter()` instead. Additionally, `TextEditor::SelectEntierDocument()` shrink the result of `EditorBase::SelectEntierDocument()` with `Selection::Extend()` if there is a `moz-<br>` element. So, `TextEditor::SelectEntinerDocument()` should set its expected selection with a call for saving the runtime cost. Then, we don't need to make `EditorBase::SelectEntierDocument()` as non-pure virtual method. So, this patch makes each its callers call `Selection->SelectAllChildren()` directly. Differential Revision: https://phabricator.services.mozilla.com/D23461 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
e4ea50f3f8
commit
534fd23ca4
@ -2301,7 +2301,9 @@ bool nsTextEditorState::SetValue(const nsAString& aValue,
|
||||
// transactions typed by user shouldn't be merged with this).
|
||||
// In this case, we need to dispatch "input" event because
|
||||
// web apps may need to know the user's operation.
|
||||
DebugOnly<nsresult> rv = textEditor->ReplaceTextAsAction(newValue);
|
||||
RefPtr<nsRange> range; // See bug 1506439
|
||||
DebugOnly<nsresult> rv =
|
||||
textEditor->ReplaceTextAsAction(newValue, range);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"Failed to set the new value");
|
||||
} else if (aFlags & eSetValue_ForXUL) {
|
||||
|
@ -2660,19 +2660,6 @@ nsresult EditorBase::InsertTextIntoTextNodeWithTransaction(
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult EditorBase::SelectEntireDocument() {
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
Element* rootElement = GetRoot();
|
||||
if (!rootElement) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
ErrorResult errorResult;
|
||||
SelectionRefPtr()->SelectAllChildren(*rootElement, errorResult);
|
||||
return errorResult.StealNSResult();
|
||||
}
|
||||
|
||||
nsINode* EditorBase::GetFirstEditableNode(nsINode* aRoot) {
|
||||
MOZ_ASSERT(aRoot);
|
||||
|
||||
|
@ -1816,6 +1816,7 @@ class EditorBase : public nsIEditor,
|
||||
* because SelectAll() creates AutoEditActionSetter but we should avoid
|
||||
* to create it as far as possible.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
virtual nsresult SelectAllInternal();
|
||||
|
||||
nsresult DetermineCurrentDirection();
|
||||
@ -1860,7 +1861,8 @@ class EditorBase : public nsIEditor,
|
||||
/**
|
||||
* Make the given selection span the entire document.
|
||||
*/
|
||||
virtual nsresult SelectEntireDocument();
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
virtual nsresult SelectEntireDocument() = 0;
|
||||
|
||||
/**
|
||||
* Helper method for scrolling the selection into view after
|
||||
|
@ -695,7 +695,7 @@ SelectAllCommand::DoCommand(const char* aCommandName,
|
||||
}
|
||||
TextEditor* textEditor = editor->AsTextEditor();
|
||||
MOZ_ASSERT(textEditor);
|
||||
return textEditor->SelectAll();
|
||||
return MOZ_KnownLive(textEditor)->SelectAll();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -3603,23 +3603,31 @@ nsresult HTMLEditor::SelectEntireDocument() {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
RefPtr<Element> rootElement = GetRoot();
|
||||
if (NS_WARN_IF(!rootElement)) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
// Protect the edit rules object from dying
|
||||
RefPtr<TextEditRules> rules(mRules);
|
||||
|
||||
// is doc empty?
|
||||
// If we're empty, don't select all children because that would select the
|
||||
// bogus node.
|
||||
if (rules->DocumentIsEmpty()) {
|
||||
// get editor root node
|
||||
Element* rootElement = GetRoot();
|
||||
|
||||
// if its empty dont select entire doc - that would select the bogus node
|
||||
nsresult rv = SelectionRefPtr()->Collapse(rootElement, 0);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
return NS_OK;
|
||||
NS_WARNING_ASSERTION(
|
||||
NS_SUCCEEDED(rv),
|
||||
"Failed to move caret to start of the editor root element");
|
||||
return rv;
|
||||
}
|
||||
|
||||
return EditorBase::SelectEntireDocument();
|
||||
// Otherwise, select all children.
|
||||
ErrorResult error;
|
||||
SelectionRefPtr()->SelectAllChildren(*rootElement, error);
|
||||
NS_WARNING_ASSERTION(
|
||||
!error.Failed(),
|
||||
"Failed to select all children of the editor root element");
|
||||
return error.StealNSResult();
|
||||
}
|
||||
|
||||
nsresult HTMLEditor::SelectAllInternal() {
|
||||
|
@ -955,6 +955,7 @@ class HTMLEditor final : public TextEditor,
|
||||
*/
|
||||
nsresult InsertParagraphSeparatorAsSubAction();
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
virtual nsresult SelectAllInternal() override;
|
||||
|
||||
/**
|
||||
@ -1521,6 +1522,7 @@ class HTMLEditor final : public TextEditor,
|
||||
/**
|
||||
* Make the given selection span the entire document.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
virtual nsresult SelectEntireDocument() override;
|
||||
|
||||
/**
|
||||
|
@ -1198,18 +1198,25 @@ nsresult TextEditor::SetTextAsSubAction(const nsAString& aString) {
|
||||
// shouldn't receive such selectionchange before the first mutation.
|
||||
AutoUpdateViewBatch preventSelectionChangeEvent(*this);
|
||||
|
||||
Element* rootElement = GetRoot();
|
||||
if (NS_WARN_IF(!rootElement)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// We want to select trailing BR node to remove all nodes to replace all,
|
||||
// but TextEditor::SelectEntireDocument doesn't select that BR node.
|
||||
if (rules->DocumentIsEmpty()) {
|
||||
// if it's empty, don't select entire doc - that would select
|
||||
// the bogus node
|
||||
Element* rootElement = GetRoot();
|
||||
if (NS_WARN_IF(!rootElement)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
rv = SelectionRefPtr()->Collapse(rootElement, 0);
|
||||
NS_WARNING_ASSERTION(
|
||||
NS_SUCCEEDED(rv),
|
||||
"Failed to move caret to start of the editor root element");
|
||||
} else {
|
||||
rv = EditorBase::SelectEntireDocument();
|
||||
ErrorResult error;
|
||||
SelectionRefPtr()->SelectAllChildren(*rootElement, error);
|
||||
NS_WARNING_ASSERTION(
|
||||
!error.Failed(),
|
||||
"Failed to select all children of the editor root element");
|
||||
rv = error.StealNSResult();
|
||||
}
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = ReplaceSelectionAsSubAction(aString);
|
||||
@ -2143,31 +2150,28 @@ nsresult TextEditor::SelectEntireDocument() {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
Element* rootElement = GetRoot();
|
||||
if (NS_WARN_IF(!rootElement)) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
// Protect the edit rules object from dying
|
||||
RefPtr<TextEditRules> rules(mRules);
|
||||
|
||||
// is doc empty?
|
||||
// If we're empty, don't select all children because that would select the
|
||||
// bogus node.
|
||||
if (rules->DocumentIsEmpty()) {
|
||||
// get root node
|
||||
Element* rootElement = GetRoot();
|
||||
if (NS_WARN_IF(!rootElement)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// if it's empty don't select entire doc - that would select the bogus node
|
||||
return SelectionRefPtr()->Collapse(rootElement, 0);
|
||||
}
|
||||
|
||||
SelectionBatcher selectionBatcher(SelectionRefPtr());
|
||||
nsresult rv = EditorBase::SelectEntireDocument();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
nsresult rv = SelectionRefPtr()->Collapse(rootElement, 0);
|
||||
NS_WARNING_ASSERTION(
|
||||
NS_SUCCEEDED(rv),
|
||||
"Failed to move caret to start of the editor root element");
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Don't select the trailing BR node if we have one
|
||||
nsCOMPtr<nsIContent> childNode;
|
||||
rv = EditorBase::GetEndChildNode(*SelectionRefPtr(),
|
||||
getter_AddRefs(childNode));
|
||||
nsresult rv = EditorBase::GetEndChildNode(*SelectionRefPtr(),
|
||||
getter_AddRefs(childNode));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
@ -2176,13 +2180,22 @@ nsresult TextEditor::SelectEntireDocument() {
|
||||
}
|
||||
|
||||
if (childNode && TextEditUtils::IsMozBR(childNode)) {
|
||||
int32_t parentOffset;
|
||||
nsINode* parentNode = GetNodeLocation(childNode, &parentOffset);
|
||||
|
||||
return SelectionRefPtr()->Extend(parentNode, parentOffset);
|
||||
ErrorResult error;
|
||||
MOZ_KnownLive(SelectionRefPtr())
|
||||
->SetStartAndEndInLimiter(RawRangeBoundary(rootElement, 0),
|
||||
EditorRawDOMPoint(childNode), error);
|
||||
NS_WARNING_ASSERTION(!error.Failed(),
|
||||
"Failed to select all children of the editor root "
|
||||
"element except the moz-<br> element");
|
||||
return error.StealNSResult();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
ErrorResult error;
|
||||
SelectionRefPtr()->SelectAllChildren(*rootElement, error);
|
||||
NS_WARNING_ASSERTION(
|
||||
!error.Failed(),
|
||||
"Failed to select all children of the editor root element");
|
||||
return error.StealNSResult();
|
||||
}
|
||||
|
||||
EventTarget* TextEditor::GetDOMEventTarget() { return mEventTarget; }
|
||||
|
@ -173,6 +173,7 @@ class TextEditor : public EditorBase, public nsIPlaintextEditor {
|
||||
*
|
||||
* @ param aString the string to be set
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
nsresult SetText(const nsAString& aString);
|
||||
|
||||
/**
|
||||
@ -183,6 +184,7 @@ class TextEditor : public EditorBase, public nsIPlaintextEditor {
|
||||
* @param aReplaceRange The range to be replaced.
|
||||
* If nullptr, all contents will be replaced.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
nsresult ReplaceTextAsAction(const nsAString& aString,
|
||||
nsRange* aReplaceRange = nullptr);
|
||||
|
||||
@ -365,6 +367,7 @@ class TextEditor : public EditorBase, public nsIPlaintextEditor {
|
||||
/**
|
||||
* Make the given selection span the entire document.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
virtual nsresult SelectEntireDocument() override;
|
||||
|
||||
/**
|
||||
|
@ -305,6 +305,7 @@ interface nsIEditor : nsISupports
|
||||
/* ------------ Selection methods -------------- */
|
||||
|
||||
/** sets the document selection to the entire contents of the document */
|
||||
[can_run_script]
|
||||
void selectAll();
|
||||
|
||||
/**
|
||||
|
@ -30,6 +30,7 @@ interface nsIEditorMailSupport : nsISupports
|
||||
* Rewrap the selected part of the document, re-quoting if necessary.
|
||||
* @param aRespectNewlines Try to maintain newlines in the original?
|
||||
*/
|
||||
[can_run_script]
|
||||
void rewrap(in boolean aRespectNewlines);
|
||||
};
|
||||
|
||||
|
@ -147,6 +147,7 @@ interface nsIHTMLEditor : nsISupports
|
||||
*
|
||||
* @param aSourceString HTML source string of the entire new document
|
||||
*/
|
||||
[can_run_script]
|
||||
void rebuildDocumentFromSource(in AString aSourceString);
|
||||
|
||||
/**
|
||||
|
@ -25,6 +25,7 @@ interface nsIInlineSpellChecker : nsISupports
|
||||
void spellCheckRange(in Range aSelection);
|
||||
|
||||
Range getMisspelledWord(in Node aNode, in long aOffset);
|
||||
[can_run_script]
|
||||
void replaceWord(in Node aNode, in long aOffset, in AString aNewword);
|
||||
void addWordToDictionary(in AString aWord);
|
||||
void removeWordFromDictionary(in AString aWord);
|
||||
|
@ -869,7 +869,8 @@ mozInlineSpellChecker::ReplaceWord(nsINode* aNode, int32_t aOffset,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
DebugOnly<nsresult> rv = mTextEditor->ReplaceTextAsAction(newword, range);
|
||||
RefPtr<TextEditor> textEditor(mTextEditor);
|
||||
DebugOnly<nsresult> rv = textEditor->ReplaceTextAsAction(newword, range);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to insert the new word");
|
||||
return NS_OK;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user