зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1705519 - Make `Document::ExecCommand` not stop handling `selectall` command when there is no editable content r=smaug
When `document.execCommand("selectall")` is called, it should behave exactly same as "Select All" in the UI for compatibility with the other browsers. And also this patch fixes a bug of the WPT. `selectionchange` event should be fired, but asynchronously. Therefore, Chrome also fails the check. Differential Revision: https://phabricator.services.mozilla.com/D112307
This commit is contained in:
Родитель
5508a33216
Коммит
7ce105e3db
|
@ -5289,7 +5289,8 @@ bool Document::ExecCommand(const nsAString& aHTMLCommandName, bool aShowUI,
|
|||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(commandData.IsPasteCommand());
|
||||
MOZ_ASSERT(commandData.IsPasteCommand() ||
|
||||
commandData.mCommand == Command::SelectAll);
|
||||
nsresult rv =
|
||||
commandManager->DoCommand(commandData.mXULCommandName, nullptr, window);
|
||||
return NS_SUCCEEDED(rv) && rv != NS_SUCCESS_DOM_NO_OPERATION;
|
||||
|
|
|
@ -4157,7 +4157,8 @@ class Document : public nsINode,
|
|||
mCommand != mozilla::Command::Copy &&
|
||||
mCommand != mozilla::Command::Paste &&
|
||||
mCommand != mozilla::Command::SetDocumentReadOnly &&
|
||||
mCommand != mozilla::Command::GetHTML;
|
||||
mCommand != mozilla::Command::GetHTML &&
|
||||
mCommand != mozilla::Command::SelectAll;
|
||||
}
|
||||
bool IsCutOrCopyCommand() const {
|
||||
return mCommand == mozilla::Command::Cut ||
|
||||
|
|
|
@ -11,15 +11,6 @@
|
|||
[ChildDocument.execCommand(copy, false, null) with a\[b\]c: checking event on executed document]
|
||||
expected: FAIL
|
||||
|
||||
[ChildDocument.execCommand(selectall, false, null) with a\[b\]c: calling execCommand]
|
||||
expected: FAIL
|
||||
|
||||
[ChildDocument.execCommand(selectall, false, null) with a\[b\]c: checking event on executed document]
|
||||
expected: FAIL
|
||||
|
||||
[ChildDocument.execCommand(selectall, false, null) with a\[b\]c: checking result content in executed document]
|
||||
expected: FAIL
|
||||
|
||||
[ParentDocument.execCommand(cut, false, null) with ab\[\]c: checking event on executed document]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -32,11 +23,3 @@
|
|||
[ParentDocument.execCommand(copy, false, null) with a\[b\]c: checking event on executed document]
|
||||
expected: FAIL
|
||||
|
||||
[ParentDocument.execCommand(selectall, false, null) with a\[b\]c: calling execCommand]
|
||||
expected: FAIL
|
||||
|
||||
[ParentDocument.execCommand(selectall, false, null) with a\[b\]c: checking event on executed document]
|
||||
expected: FAIL
|
||||
|
||||
[ParentDocument.execCommand(selectall, false, null) with a\[b\]c: checking result content in executed document]
|
||||
expected: FAIL
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
<script src=../include/tests.js></script>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<div contenteditable id="editor">abc</div>
|
||||
<iframe srcdoc="<div contenteditable id='editor'>def</div><span>ghi</span>"></iframe>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
|
@ -19,7 +17,7 @@ setup({explicit_done: true});
|
|||
// "cut", "copy", "paste" and "selectall" commands should work without DOM tree
|
||||
// modification for making web apps can implement their own editor without
|
||||
// editable element.
|
||||
function runTests() {
|
||||
async function runTests() {
|
||||
let parentWindow = window;
|
||||
let parentDocument = document;
|
||||
let parentSelection = parentDocument.getSelection();
|
||||
|
@ -34,17 +32,17 @@ function runTests() {
|
|||
|
||||
// execCommand() in child document shouldn't affect to focused parent
|
||||
// document.
|
||||
doTest(parentWindow, parentDocument, parentSelection, parentEditor,
|
||||
await doTest(parentWindow, parentDocument, parentSelection, parentEditor,
|
||||
childWindow, childDocument, childSelection, childEditor, false);
|
||||
// execCommand() in parent document shouldn't affect to focused child
|
||||
// document but "cut" and "copy" may affect the focused child document.
|
||||
doTest(childWindow, childDocument, childSelection, childEditor,
|
||||
await doTest(childWindow, childDocument, childSelection, childEditor,
|
||||
parentWindow, parentDocument, parentSelection, parentEditor, true);
|
||||
|
||||
done();
|
||||
}
|
||||
|
||||
function doTest(aFocusWindow, aFocusDocument, aFocusSelection, aFocusEditor,
|
||||
async function doTest(aFocusWindow, aFocusDocument, aFocusSelection, aFocusEditor,
|
||||
aExecWindow, aExecDocument, aExecSelection, aExecEditor,
|
||||
aExecInParent) {
|
||||
const kTests = [
|
||||
|
@ -152,7 +150,7 @@ function doTest(aFocusWindow, aFocusDocument, aFocusSelection, aFocusEditor,
|
|||
// "selectall" command should be available without editable content.
|
||||
{command: "selectall", value: null,
|
||||
focusContent: "a[b]c", execContent: "a[b]c",
|
||||
expectedFocusContent: "a[b]c", expectedExecContent: "[abc",
|
||||
expectedFocusContent: "a[b]c", expectedExecContent: undefined,
|
||||
event: "selectionchange", expectedFiredInFocus: false, expectedFiredInExec: true,
|
||||
expectedResult: true,
|
||||
},
|
||||
|
@ -387,6 +385,16 @@ function doTest(aFocusWindow, aFocusDocument, aFocusSelection, aFocusEditor,
|
|||
},
|
||||
];
|
||||
|
||||
async function waitForCondition(aCheckFunc) {
|
||||
let retry = 60;
|
||||
while (retry--) {
|
||||
if (aCheckFunc()) {
|
||||
return;
|
||||
}
|
||||
await new Promise(resolve => requestAnimationFrame(resolve));
|
||||
}
|
||||
}
|
||||
|
||||
for (const kTest of kTests) {
|
||||
// Skip unsupported command since it's not purpose of this tests whether
|
||||
// each command is supported on the browser.
|
||||
|
@ -419,10 +427,22 @@ function doTest(aFocusWindow, aFocusDocument, aFocusSelection, aFocusEditor,
|
|||
let ret = aExecDocument.execCommand(kTest.command, false, kTest.value);
|
||||
assert_equals(ret, kTest.expectedResult, `execCommand should return ${kTest.expectedResult}`);
|
||||
}, `${kDescription}: calling execCommand`);
|
||||
if (kTest.event === "selectionchange") {
|
||||
test(function () {
|
||||
assert_false(eventFiredOnFocusDocument,
|
||||
`"${kTest.event}" event should not be fired synchronously on focused document`);
|
||||
assert_false(eventFiredOnExecDocument,
|
||||
`"${kTest.event}" event should not be fired synchronously on executed document`);
|
||||
}, `${kDescription}: checking unexpected synchronous event`);
|
||||
await waitForCondition(() => eventFiredOnFocusDocument && eventFiredOnExecDocument);
|
||||
// TODO: Whether select all changes selection in the focused document depends on the
|
||||
// implementation of "Select All".
|
||||
} else {
|
||||
test(function () {
|
||||
assert_equals(eventFiredOnFocusDocument, kTest.expectedFiredInFocus,
|
||||
`"${kTest.event}" event should${kTest.expectedFiredInFocus ? "" : " not"} be fired`);
|
||||
}, `${kDescription}: checking event on focused document`);
|
||||
}
|
||||
test(function () {
|
||||
assert_equals(eventFiredOnExecDocument, kTest.expectedFiredInExec,
|
||||
`"${kTest.event}" event should${kTest.expectedFiredInExec ? "" : " not"} be fired`);
|
||||
|
@ -434,10 +454,18 @@ function doTest(aFocusWindow, aFocusDocument, aFocusSelection, aFocusEditor,
|
|||
assert_equals(aFocusEditor.innerHTML, kTest.expectedFocusContent);
|
||||
}, `${kDescription}: checking result content in focused document`);
|
||||
test(function () {
|
||||
if (kTest.command === "selectall") {
|
||||
assert_true(aExecSelection.rangeCount > 0);
|
||||
assert_equals(
|
||||
aExecSelection.toString().replace(/[\r\n]/g, ""),
|
||||
aExecDocument.body.textContent.replace(/[\r\n]/g, "")
|
||||
);
|
||||
} else {
|
||||
if (aExecSelection.rangeCount) {
|
||||
addBrackets(aExecSelection.getRangeAt(0));
|
||||
}
|
||||
assert_equals(aExecEditor.innerHTML, kTest.expectedExecContent);
|
||||
}
|
||||
}, `${kDescription}: checking result content in executed document`);
|
||||
aFocusDocument.removeEventListener(kTest.event, handlerOnFocusDocument, {capture: true});
|
||||
aExecDocument.removeEventListener(kTest.event, handlerOnExecDocument, {capture: true});
|
||||
|
@ -492,3 +520,7 @@ function doTest(aFocusWindow, aFocusDocument, aFocusSelection, aFocusEditor,
|
|||
|
||||
window.addEventListener("load", runTests, {once: true});
|
||||
</script>
|
||||
<body>
|
||||
<div contenteditable id="editor">abc</div>
|
||||
<iframe srcdoc="<div contenteditable id='editor'>def</div><span>ghi</span>"></iframe>
|
||||
</body>
|
||||
|
|
Загрузка…
Ссылка в новой задаче