Backed out changeset 93cf5f317f98 (bug 1676785) for causing mochitest failures in test_input_value_set_preserve_undo.xhtml
CLOSED TREE
This commit is contained in:
@@ -276,6 +276,10 @@ interface nsISelectionController : nsISelectionDisplay
|
|||||||
*/
|
*/
|
||||||
void scrollCharacter(in boolean right);
|
void scrollCharacter(in boolean right);
|
||||||
|
|
||||||
|
/** SelectAll will select the whole page
|
||||||
|
*/
|
||||||
|
void selectAll();
|
||||||
|
|
||||||
/** CheckVisibility will return true if textnode and offsets are actually rendered
|
/** CheckVisibility will return true if textnode and offsets are actually rendered
|
||||||
* in the current precontext.
|
* in the current precontext.
|
||||||
* @param aNode textNode to test
|
* @param aNode textNode to test
|
||||||
|
|||||||
@@ -69,7 +69,6 @@ support-files =
|
|||||||
file_document-element-inserted-inner.xhtml
|
file_document-element-inserted-inner.xhtml
|
||||||
[test_domparsing.xhtml]
|
[test_domparsing.xhtml]
|
||||||
[test_fileconstructor.xhtml]
|
[test_fileconstructor.xhtml]
|
||||||
[test_input_value_set_preserve_undo.xhtml]
|
|
||||||
[test_nsITextInputProcessor.xhtml]
|
[test_nsITextInputProcessor.xhtml]
|
||||||
[test_permission_isHandlingUserInput.xhtml]
|
[test_permission_isHandlingUserInput.xhtml]
|
||||||
support-files = ../dummy.html
|
support-files = ../dummy.html
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
<?xml version="1.0"?>
|
|
||||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
|
||||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
|
|
||||||
<window title="Bug 1676785"
|
|
||||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
|
||||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
|
||||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
|
||||||
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
|
||||||
<script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
|
||||||
<html:body>
|
|
||||||
<xul:hbox>
|
|
||||||
<html:input id="xul" />
|
|
||||||
</xul:hbox>
|
|
||||||
<html:div>
|
|
||||||
<html:input id="non-xul" />
|
|
||||||
</html:div>
|
|
||||||
</html:body>
|
|
||||||
<script class="testbody">
|
|
||||||
SimpleTest.waitForExplicitFinish();
|
|
||||||
|
|
||||||
function shouldPreserveHistory(input, preserve) {
|
|
||||||
input.focus();
|
|
||||||
input.value = "abc";
|
|
||||||
input.value = "def";
|
|
||||||
synthesizeKey("z", {ctrlKey: true});
|
|
||||||
(preserve ? is : isnot)(input.value, "abc", `Expected ${input.id} to ${preserve ? "" : "not "}preserve undo history when setting .value`);
|
|
||||||
}
|
|
||||||
|
|
||||||
window.onload = function() {
|
|
||||||
shouldPreserveHistory(document.getElementById("xul"), true);
|
|
||||||
shouldPreserveHistory(document.getElementById("non-xul"), false);
|
|
||||||
|
|
||||||
SimpleTest.finish();
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</window>
|
|
||||||
@@ -2641,14 +2641,10 @@ nsresult HTMLInputElement::SetValueInternal(const nsAString& aValue,
|
|||||||
|
|
||||||
// We want to remember if the SetValueInternal() call is being made for a XUL
|
// We want to remember if the SetValueInternal() call is being made for a XUL
|
||||||
// element. We do that by looking at the parent node here, and if that node
|
// element. We do that by looking at the parent node here, and if that node
|
||||||
// is a XUL node, we consider our control a XUL control. XUL controls preserve
|
// is a XUL node, we consider our control a XUL control.
|
||||||
// edit history across value setters.
|
nsIContent* parent = GetParent();
|
||||||
//
|
if (parent && parent->IsXULElement()) {
|
||||||
// TODO(emilio): Rather than doing this maybe add an attribute instead and
|
aFlags |= TextControlState::eSetValue_ForXUL;
|
||||||
// read it only on chrome docs or something? That'd allow front-end code to
|
|
||||||
// move away from xul without weird side-effects.
|
|
||||||
if (mParent && mParent->IsXULElement()) {
|
|
||||||
aFlags |= TextControlState::eSetValue_PreserveHistory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (GetValueMode()) {
|
switch (GetValueMode()) {
|
||||||
|
|||||||
@@ -347,6 +347,7 @@ class TextInputSelectionController final : public nsSupportsWeakReference,
|
|||||||
NS_IMETHOD ScrollPage(bool aForward) override;
|
NS_IMETHOD ScrollPage(bool aForward) override;
|
||||||
NS_IMETHOD ScrollLine(bool aForward) override;
|
NS_IMETHOD ScrollLine(bool aForward) override;
|
||||||
NS_IMETHOD ScrollCharacter(bool aRight) override;
|
NS_IMETHOD ScrollCharacter(bool aRight) override;
|
||||||
|
NS_IMETHOD SelectAll(void) override;
|
||||||
NS_IMETHOD CheckVisibility(nsINode* node, int16_t startOffset,
|
NS_IMETHOD CheckVisibility(nsINode* node, int16_t startOffset,
|
||||||
int16_t EndOffset, bool* _retval) override;
|
int16_t EndOffset, bool* _retval) override;
|
||||||
virtual nsresult CheckVisibilityContent(nsIContent* aNode,
|
virtual nsresult CheckVisibilityContent(nsIContent* aNode,
|
||||||
@@ -751,6 +752,15 @@ TextInputSelectionController::ScrollCharacter(bool aRight) {
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
TextInputSelectionController::SelectAll() {
|
||||||
|
if (!mFrameSelection) {
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
RefPtr<nsFrameSelection> frameSelection = mFrameSelection;
|
||||||
|
return frameSelection->SelectAll();
|
||||||
|
}
|
||||||
|
|
||||||
void TextInputSelectionController::SelectionWillTakeFocus() {
|
void TextInputSelectionController::SelectionWillTakeFocus() {
|
||||||
if (mFrameSelection) {
|
if (mFrameSelection) {
|
||||||
if (PresShell* shell = mFrameSelection->GetPresShell()) {
|
if (PresShell* shell = mFrameSelection->GetPresShell()) {
|
||||||
@@ -2766,16 +2776,61 @@ bool TextControlState::SetValueWithTextEditor(
|
|||||||
// by script.
|
// by script.
|
||||||
AutoInputEventSuppresser suppressInputEventDispatching(textEditor);
|
AutoInputEventSuppresser suppressInputEventDispatching(textEditor);
|
||||||
|
|
||||||
|
if (aHandlingSetValue.GetSetValueFlags() & eSetValue_ForXUL) {
|
||||||
|
// On XUL <textbox> element, we need to preserve existing undo
|
||||||
|
// transactions.
|
||||||
|
// XXX Do we really need to do such complicated optimization?
|
||||||
|
// This was landed for web pages which set <textarea> value
|
||||||
|
// per line (bug 518122). For example:
|
||||||
|
// for (;;) {
|
||||||
|
// textarea.value += oneLineText + "\n";
|
||||||
|
// }
|
||||||
|
// However, this path won't be used in web content anymore.
|
||||||
|
nsCOMPtr<nsISelectionController> kungFuDeathGrip = mSelCon.get();
|
||||||
|
// Use nsString to avoid copying string buffer in most cases.
|
||||||
|
nsString currentValue;
|
||||||
|
if (aHandlingSetValue.GetOldValue()) {
|
||||||
|
currentValue.Assign(*aHandlingSetValue.GetOldValue());
|
||||||
|
} else {
|
||||||
|
mBoundFrame->GetText(currentValue);
|
||||||
|
}
|
||||||
|
uint32_t currentLength = currentValue.Length();
|
||||||
|
uint32_t newlength = aHandlingSetValue.GetSettingValue().Length();
|
||||||
|
if (!currentLength ||
|
||||||
|
!StringBeginsWith(aHandlingSetValue.GetSettingValue(), currentValue)) {
|
||||||
|
// Replace the whole text.
|
||||||
|
currentLength = 0;
|
||||||
|
kungFuDeathGrip->SelectAll();
|
||||||
|
} else {
|
||||||
|
// Collapse selection to the end so that we can append data.
|
||||||
|
mBoundFrame->SelectAllOrCollapseToEndOfText(false);
|
||||||
|
}
|
||||||
|
const nsAString& insertValue = StringTail(
|
||||||
|
aHandlingSetValue.GetSettingValue(), newlength - currentLength);
|
||||||
|
|
||||||
|
if (insertValue.IsEmpty()) {
|
||||||
|
// In this case, we makes the editor stop dispatching "input"
|
||||||
|
// event so that passing nullptr as nsIPrincipal is safe for
|
||||||
|
// now.
|
||||||
|
nsresult rv = textEditor->DeleteSelectionAsAction(
|
||||||
|
nsIEditor::eNone, nsIEditor::eNoStrip, nullptr);
|
||||||
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
||||||
|
"TextEditor::DeleteSelectionAsAction() failed");
|
||||||
|
return rv != NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
// In this case, we makes the editor stop dispatching "input"
|
||||||
|
// event so that passing nullptr as nsIPrincipal is safe for
|
||||||
|
// now.
|
||||||
|
nsresult rv = textEditor->InsertTextAsAction(insertValue, nullptr);
|
||||||
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
||||||
|
"TextEditor::InsertTextAsAction() failed");
|
||||||
|
return rv != NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
// On <input> or <textarea>, we shouldn't preserve existing undo
|
// On <input> or <textarea>, we shouldn't preserve existing undo
|
||||||
// transactions because other browsers do not preserve them too
|
// transactions because other browsers do not preserve them too
|
||||||
// and not preserving transactions makes setting value faster.
|
// and not preserving transactions makes setting value faster.
|
||||||
//
|
AutoDisableUndo disableUndo(textEditor);
|
||||||
// (Except if chrome opts into this behavior).
|
|
||||||
Maybe<AutoDisableUndo> disableUndo;
|
|
||||||
if (!(aHandlingSetValue.GetSetValueFlags() & eSetValue_PreserveHistory)) {
|
|
||||||
disableUndo.emplace(textEditor);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selection) {
|
if (selection) {
|
||||||
// Since we don't use undo transaction, we don't need to store
|
// Since we don't use undo transaction, we don't need to store
|
||||||
// selection state. SetText will set selection to tail.
|
// selection state. SetText will set selection to tail.
|
||||||
|
|||||||
@@ -194,10 +194,10 @@ class TextControlState final : public SupportsWeakPtr {
|
|||||||
// TODO(mbrodesser): update comment and enumerator identifier to reflect
|
// TODO(mbrodesser): update comment and enumerator identifier to reflect
|
||||||
// that also the direction is set to forward.
|
// that also the direction is set to forward.
|
||||||
eSetValue_MoveCursorToEndIfValueChanged = 1 << 4,
|
eSetValue_MoveCursorToEndIfValueChanged = 1 << 4,
|
||||||
|
// The value is changed for a XUL text control as opposed to for an HTML
|
||||||
// The value change should preserve undo history.
|
// text control. Such value changes are different in that they preserve the
|
||||||
eSetValue_PreserveHistory = 1 << 5,
|
// undo history.
|
||||||
|
eSetValue_ForXUL = 1 << 5,
|
||||||
// Whether it should be tried to move the cursor to the beginning of the
|
// Whether it should be tried to move the cursor to the beginning of the
|
||||||
// text control and set the selection direction to "forward".
|
// text control and set the selection direction to "forward".
|
||||||
// TODO(mbrodesser): As soon as "none" is supported
|
// TODO(mbrodesser): As soon as "none" is supported
|
||||||
|
|||||||
@@ -2481,6 +2481,12 @@ PresShell::CompleteMove(bool aForward, bool aExtend) {
|
|||||||
nsISelectionController::SCROLL_FOR_CARET_MOVE);
|
nsISelectionController::SCROLL_FOR_CARET_MOVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PresShell::SelectAll() {
|
||||||
|
RefPtr<nsFrameSelection> frameSelection = mSelection;
|
||||||
|
return frameSelection->SelectAll();
|
||||||
|
}
|
||||||
|
|
||||||
static void DoCheckVisibility(nsPresContext* aPresContext, nsIContent* aNode,
|
static void DoCheckVisibility(nsPresContext* aPresContext, nsIContent* aNode,
|
||||||
int16_t aStartOffset, int16_t aEndOffset,
|
int16_t aStartOffset, int16_t aEndOffset,
|
||||||
bool* aRetval) {
|
bool* aRetval) {
|
||||||
|
|||||||
@@ -1320,6 +1320,7 @@ class PresShell final : public nsStubDocumentObserver,
|
|||||||
NS_IMETHOD ScrollCharacter(bool aRight) override;
|
NS_IMETHOD ScrollCharacter(bool aRight) override;
|
||||||
NS_IMETHOD CompleteScroll(bool aForward) override;
|
NS_IMETHOD CompleteScroll(bool aForward) override;
|
||||||
NS_IMETHOD CompleteMove(bool aForward, bool aExtend) override;
|
NS_IMETHOD CompleteMove(bool aForward, bool aExtend) override;
|
||||||
|
NS_IMETHOD SelectAll() override;
|
||||||
NS_IMETHOD CheckVisibility(nsINode* node, int16_t startOffset,
|
NS_IMETHOD CheckVisibility(nsINode* node, int16_t startOffset,
|
||||||
int16_t EndOffset, bool* _retval) override;
|
int16_t EndOffset, bool* _retval) override;
|
||||||
nsresult CheckVisibilityContent(nsIContent* aNode, int16_t aStartOffset,
|
nsresult CheckVisibilityContent(nsIContent* aNode, int16_t aStartOffset,
|
||||||
|
|||||||
@@ -2129,6 +2129,27 @@ nsFrameSelection::CreateRangeExtendedToSomewhere(
|
|||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult nsFrameSelection::SelectAll() {
|
||||||
|
nsCOMPtr<nsIContent> rootContent;
|
||||||
|
if (mLimiters.mLimiter) {
|
||||||
|
rootContent = mLimiters.mLimiter; // addrefit
|
||||||
|
} else if (mLimiters.mAncestorLimiter) {
|
||||||
|
rootContent = mLimiters.mAncestorLimiter;
|
||||||
|
} else {
|
||||||
|
NS_ENSURE_STATE(mPresShell);
|
||||||
|
Document* doc = mPresShell->GetDocument();
|
||||||
|
if (!doc) return NS_ERROR_FAILURE;
|
||||||
|
rootContent = doc->GetRootElement();
|
||||||
|
if (!rootContent) return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
int32_t numChildren = rootContent->GetChildCount();
|
||||||
|
SetChangeReasons(nsISelectionListener::NO_REASON);
|
||||||
|
int8_t index = GetIndexFromSelectionType(SelectionType::eNormal);
|
||||||
|
AutoPrepareFocusRange prep(mDomSelections[index], false);
|
||||||
|
return TakeFocus(rootContent, 0, numChildren, CARET_ASSOCIATE_BEFORE,
|
||||||
|
FocusMode::kCollapseToNewPoint);
|
||||||
|
}
|
||||||
|
|
||||||
//////////END FRAMESELECTION
|
//////////END FRAMESELECTION
|
||||||
|
|
||||||
void nsFrameSelection::StartBatchChanges() { mBatching.mCounter++; }
|
void nsFrameSelection::StartBatchChanges() { mBatching.mCounter++; }
|
||||||
|
|||||||
@@ -608,6 +608,12 @@ class nsFrameSelection final {
|
|||||||
eLogical);
|
eLogical);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select All will generally be called from the nsiselectioncontroller
|
||||||
|
* implementations. it will select the whole doc
|
||||||
|
*/
|
||||||
|
MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult SelectAll();
|
||||||
|
|
||||||
/** Sets/Gets The display selection enum.
|
/** Sets/Gets The display selection enum.
|
||||||
*/
|
*/
|
||||||
void SetDisplaySelection(int16_t aState) { mDisplaySelection = aState; }
|
void SetDisplaySelection(int16_t aState) { mDisplaySelection = aState; }
|
||||||
|
|||||||
Reference in New Issue
Block a user