Bug 1561435 - Format editor/, a=automatic-formatting

# ignore-this-changeset

Differential Revision: https://phabricator.services.mozilla.com/D35901

--HG--
extra : source : 31c98530f9be7521baab316d7edc309361623fb1
This commit is contained in:
Victor Porof 2019-07-05 10:45:46 +02:00
parent dcd795c16b
commit 5065489a4e
6 changed files with 229 additions and 169 deletions

View file

@ -45,7 +45,6 @@ module.exports = {
"overrides": [{
"files": [
"devtools/**",
"editor/**",
"extensions/**",
"gfx/**",
"gradle/**",

View file

@ -40,7 +40,6 @@ toolkit/components/telemetry/datareporting-prefs.js
toolkit/components/telemetry/healthreport-prefs.js
# Ignore all top-level directories for now.
editor/**
extensions/**
gfx/**
gradle/**

View file

@ -2,9 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var EXPORTED_SYMBOLS = [
"onSpellCheck",
];
var EXPORTED_SYMBOLS = ["onSpellCheck"];
const SPELL_CHECK_ENDED_TOPIC = "inlineSpellChecker-spellCheck-ended";
const SPELL_CHECK_STARTED_TOPIC = "inlineSpellChecker-spellCheck-started";
@ -32,8 +30,9 @@ function onSpellCheck(editableElement, callback) {
let win = editableElement.ownerGlobal;
editor = win.docShell.editingSession.getEditorForWindow(win);
}
if (!editor)
if (!editor) {
throw new Error("Unable to find editor for element " + editableElement);
}
try {
// False is important here. Pass false so that the inline spell checker
@ -50,31 +49,40 @@ function onSpellCheck(editableElement, callback) {
let count = 0;
function observe(subj, topic, data) {
if (subj != editor)
if (subj != editor) {
return;
}
count = 0;
let expectedTopic = waitingForEnded ? SPELL_CHECK_ENDED_TOPIC :
SPELL_CHECK_STARTED_TOPIC;
if (topic != expectedTopic)
let expectedTopic = waitingForEnded
? SPELL_CHECK_ENDED_TOPIC
: SPELL_CHECK_STARTED_TOPIC;
if (topic != expectedTopic) {
Cu.reportError("Expected " + expectedTopic + " but got " + topic + "!");
}
waitingForEnded = !waitingForEnded;
}
// eslint-disable-next-line mozilla/use-services
let os = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
let os = Cc["@mozilla.org/observer-service;1"].getService(
Ci.nsIObserverService
);
os.addObserver(observe, SPELL_CHECK_STARTED_TOPIC);
os.addObserver(observe, SPELL_CHECK_ENDED_TOPIC);
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
timer.init(function tick() {
// Wait an arbitrarily large number -- 50 -- turns of the event loop before
// declaring that no spell checks will start.
if (waitingForEnded || ++count < 50)
return;
timer.cancel();
os.removeObserver(observe, SPELL_CHECK_STARTED_TOPIC);
os.removeObserver(observe, SPELL_CHECK_ENDED_TOPIC);
callback();
}, 0, Ci.nsITimer.TYPE_REPEATING_SLACK);
timer.init(
function tick() {
// Wait an arbitrarily large number -- 50 -- turns of the event loop before
// declaring that no spell checks will start.
if (waitingForEnded || ++count < 50) {
return;
}
timer.cancel();
os.removeObserver(observe, SPELL_CHECK_STARTED_TOPIC);
os.removeObserver(observe, SPELL_CHECK_ENDED_TOPIC);
callback();
},
0,
Ci.nsITimer.TYPE_REPEATING_SLACK
);
}

View file

@ -1,57 +1,79 @@
add_task(async function() {
await new Promise(resolve => waitForFocus(resolve, window));
const kPageURL = "http://example.org/browser/editor/libeditor/tests/bug527935.html";
await BrowserTestUtils.withNewTab({
gBrowser,
url: kPageURL,
}, async function(aBrowser) {
var popupShown = false;
function listener() {
popupShown = true;
}
SpecialPowers.addAutoCompletePopupEventListener(window, "popupshowing", listener);
const kPageURL =
"http://example.org/browser/editor/libeditor/tests/bug527935.html";
await BrowserTestUtils.withNewTab(
{
gBrowser,
url: kPageURL,
},
async function(aBrowser) {
var popupShown = false;
function listener() {
popupShown = true;
}
SpecialPowers.addAutoCompletePopupEventListener(
window,
"popupshowing",
listener
);
await ContentTask.spawn(aBrowser, {}, async function() {
var window = content.window.wrappedJSObject;
var document = window.document;
var formTarget = document.getElementById("formTarget");
var initValue = document.getElementById("initValue");
await ContentTask.spawn(aBrowser, {}, async function() {
var window = content.window.wrappedJSObject;
var document = window.document;
var formTarget = document.getElementById("formTarget");
var initValue = document.getElementById("initValue");
window.loadPromise = new Promise(resolve => {
formTarget.onload = resolve;
window.loadPromise = new Promise(resolve => {
formTarget.onload = resolve;
});
initValue.focus();
initValue.value = "foo";
});
initValue.focus();
initValue.value = "foo";
});
EventUtils.synthesizeKey("KEY_Enter");
EventUtils.synthesizeKey("KEY_Enter");
await ContentTask.spawn(aBrowser, {}, async function() {
var window = content.window.wrappedJSObject;
var document = window.document;
await ContentTask.spawn(aBrowser, {}, async function() {
var window = content.window.wrappedJSObject;
var document = window.document;
await window.loadPromise;
await window.loadPromise;
var newInput = document.createElement("input");
newInput.setAttribute("name", "test");
document.body.appendChild(newInput);
var newInput = document.createElement("input");
newInput.setAttribute("name", "test");
document.body.appendChild(newInput);
var event = document.createEvent("KeyboardEvent");
var event = document.createEvent("KeyboardEvent");
event.initKeyEvent(
"keypress",
true,
true,
null,
false,
false,
false,
false,
0,
"f".charCodeAt(0)
);
newInput.value = "";
newInput.focus();
newInput.dispatchEvent(event);
});
event.initKeyEvent("keypress", true, true, null, false, false,
false, false, 0, "f".charCodeAt(0));
newInput.value = "";
newInput.focus();
newInput.dispatchEvent(event);
});
await new Promise(resolve => hitEventLoop(resolve, 100));
await new Promise(resolve => hitEventLoop(resolve, 100));
ok(!popupShown, "Popup must not be opened");
SpecialPowers.removeAutoCompletePopupEventListener(window, "popupshowing", listener);
});
ok(!popupShown, "Popup must not be opened");
SpecialPowers.removeAutoCompletePopupEventListener(
window,
"popupshowing",
listener
);
}
);
});
function hitEventLoop(func, times) {

View file

@ -1,117 +1,145 @@
add_task(async function() {
await new Promise(resolve => waitForFocus(resolve, window));
const kPageURL = "http://example.org/browser/editor/libeditor/tests/bug629172.html";
await BrowserTestUtils.withNewTab({
gBrowser,
url: kPageURL,
}, async function(browser) {
await ContentTask.spawn(browser, {}, async function() {
var window = content.window.wrappedJSObject;
var document = window.document;
// Note: Using the with keyword, we would have been able to write this as:
//
// with (window) {
// Screenshots = {};
// // so on
// }
//
// However, browser-chrome tests are somehow forced to run in strict mode,
// which doesn't permit the usage of the with keyword, turning the following
// into the ugliest test you've ever seen. :(
var LTRRef = document.getElementById("ltr-ref");
var RTLRef = document.getElementById("rtl-ref");
window.Screenshots = {};
// generate the reference screenshots
LTRRef.style.display = "";
document.body.clientWidth;
window.Screenshots.ltr = window.snapshotWindow(window);
LTRRef.remove();
RTLRef.style.display = "";
document.body.clientWidth;
window.Screenshots.rtl = window.snapshotWindow(window);
RTLRef.remove();
window.Screenshots.get = function(dir) {
return this[dir];
};
});
function simulateCtrlShiftX(aBrowser) {
// In e10s, the keypress event will be dispatched to the content process,
// but in non-e10s it is handled by the browser UI code and hence won't
// reach the web page. As a result, we need to observe the event in
// the content process only in e10s mode.
if (gMultiProcessBrowser) {
return EventUtils.synthesizeAndWaitKey("x", {accelKey: true, shiftKey: true});
}
EventUtils.synthesizeKey("x", {accelKey: true, shiftKey: true});
return Promise.resolve();
}
async function testDirection(initDir, aBrowser) {
await ContentTask.spawn(aBrowser, {initialDir: initDir}, function({initialDir}) {
const kPageURL =
"http://example.org/browser/editor/libeditor/tests/bug629172.html";
await BrowserTestUtils.withNewTab(
{
gBrowser,
url: kPageURL,
},
async function(browser) {
await ContentTask.spawn(browser, {}, async function() {
var window = content.window.wrappedJSObject;
var document = window.document;
var t = window.t = document.createElement("textarea");
t.setAttribute("dir", initialDir);
t.value = "test.";
window.inputEventCount = 0;
t.oninput = function() { window.inputEventCount++; };
document.getElementById("content").appendChild(t);
// Note: Using the with keyword, we would have been able to write this as:
//
// with (window) {
// Screenshots = {};
// // so on
// }
//
// However, browser-chrome tests are somehow forced to run in strict mode,
// which doesn't permit the usage of the with keyword, turning the following
// into the ugliest test you've ever seen. :(
var LTRRef = document.getElementById("ltr-ref");
var RTLRef = document.getElementById("rtl-ref");
window.Screenshots = {};
// generate the reference screenshots
LTRRef.style.display = "";
document.body.clientWidth;
var s1 = window.snapshotWindow(window);
window.ok = ok; // for assertSnapshots
window.
assertSnapshots(s1, window.Screenshots.get(initialDir), true,
/* fuzz = */ null,
"Textarea before switching the direction from " +
initialDir,
"Reference " + initialDir + " textarea");
t.focus();
is(window.inputEventCount, 0, "input event count must be 0 before");
window.Screenshots.ltr = window.snapshotWindow(window);
LTRRef.remove();
RTLRef.style.display = "";
document.body.clientWidth;
window.Screenshots.rtl = window.snapshotWindow(window);
RTLRef.remove();
window.Screenshots.get = function(dir) {
return this[dir];
};
});
await simulateCtrlShiftX(aBrowser);
await ContentTask.spawn(aBrowser, {initialDir: initDir}, function({initialDir}) {
var window = content.window.wrappedJSObject;
var expectedDir = initialDir == "ltr" ? "rtl" : "ltr";
is(window.t.getAttribute("dir"), expectedDir,
"The dir attribute must be correctly updated");
is(window.inputEventCount, 1, "input event count must be 1 after");
window.t.blur();
var s2 = window.snapshotWindow(window);
window.ok = ok; // for assertSnapshots
window.
assertSnapshots(s2, window.Screenshots.get(expectedDir), true,
/* fuzz = */ null,
"Textarea after switching the direction from " +
initialDir,
"Reference " + expectedDir + " textarea");
window.t.focus();
is(window.inputEventCount, 1, "input event count must be 1 before");
});
await simulateCtrlShiftX(aBrowser);
await ContentTask.spawn(aBrowser, {initialDir: initDir}, function({initialDir}) {
var window = content.window.wrappedJSObject;
is(window.inputEventCount, 2, "input event count must be 2 after");
is(window.t.getAttribute("dir"), initialDir == "ltr" ? "ltr" : "rtl", "The dir attribute must be correctly updated");
window.t.blur();
var s3 = window.snapshotWindow(window);
window.ok = ok; // for assertSnapshots
window.
assertSnapshots(s3, window.Screenshots.get(initialDir), true,
/* fuzz = */ null,
"Textarea after switching back the direction to " +
initialDir,
"Reference " + initialDir + " textarea");
window.t.remove();
});
function simulateCtrlShiftX(aBrowser) {
// In e10s, the keypress event will be dispatched to the content process,
// but in non-e10s it is handled by the browser UI code and hence won't
// reach the web page. As a result, we need to observe the event in
// the content process only in e10s mode.
if (gMultiProcessBrowser) {
return EventUtils.synthesizeAndWaitKey("x", {
accelKey: true,
shiftKey: true,
});
}
EventUtils.synthesizeKey("x", { accelKey: true, shiftKey: true });
return Promise.resolve();
}
async function testDirection(initDir, aBrowser) {
await ContentTask.spawn(aBrowser, { initialDir: initDir }, function({
initialDir,
}) {
var window = content.window.wrappedJSObject;
var document = window.document;
var t = (window.t = document.createElement("textarea"));
t.setAttribute("dir", initialDir);
t.value = "test.";
window.inputEventCount = 0;
t.oninput = function() {
window.inputEventCount++;
};
document.getElementById("content").appendChild(t);
document.body.clientWidth;
var s1 = window.snapshotWindow(window);
window.ok = ok; // for assertSnapshots
window.assertSnapshots(
s1,
window.Screenshots.get(initialDir),
true,
/* fuzz = */ null,
"Textarea before switching the direction from " + initialDir,
"Reference " + initialDir + " textarea"
);
t.focus();
is(window.inputEventCount, 0, "input event count must be 0 before");
});
await simulateCtrlShiftX(aBrowser);
await ContentTask.spawn(aBrowser, { initialDir: initDir }, function({
initialDir,
}) {
var window = content.window.wrappedJSObject;
var expectedDir = initialDir == "ltr" ? "rtl" : "ltr";
is(
window.t.getAttribute("dir"),
expectedDir,
"The dir attribute must be correctly updated"
);
is(window.inputEventCount, 1, "input event count must be 1 after");
window.t.blur();
var s2 = window.snapshotWindow(window);
window.ok = ok; // for assertSnapshots
window.assertSnapshots(
s2,
window.Screenshots.get(expectedDir),
true,
/* fuzz = */ null,
"Textarea after switching the direction from " + initialDir,
"Reference " + expectedDir + " textarea"
);
window.t.focus();
is(window.inputEventCount, 1, "input event count must be 1 before");
});
await simulateCtrlShiftX(aBrowser);
await ContentTask.spawn(aBrowser, { initialDir: initDir }, function({
initialDir,
}) {
var window = content.window.wrappedJSObject;
is(window.inputEventCount, 2, "input event count must be 2 after");
is(
window.t.getAttribute("dir"),
initialDir == "ltr" ? "ltr" : "rtl",
"The dir attribute must be correctly updated"
);
window.t.blur();
var s3 = window.snapshotWindow(window);
window.ok = ok; // for assertSnapshots
window.assertSnapshots(
s3,
window.Screenshots.get(initialDir),
true,
/* fuzz = */ null,
"Textarea after switching back the direction to " + initialDir,
"Reference " + initialDir + " textarea"
);
window.t.remove();
});
}
await testDirection("ltr", browser);
await testDirection("rtl", browser);
}
await testDirection("ltr", browser);
await testDirection("rtl", browser);
});
);
});

View file

@ -3,7 +3,11 @@ function isSpellingCheckOk(aEditor, aMisspelledWords) {
var sel = selcon.getSelection(selcon.SELECTION_SPELLCHECK);
var numWords = sel.rangeCount;
is(numWords, aMisspelledWords.length, "Correct number of misspellings and words.");
is(
numWords,
aMisspelledWords.length,
"Correct number of misspellings and words."
);
if (numWords !== aMisspelledWords.length) {
return false;