зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1719110 - Don't use sync IPC to show suggestion by spellchecker. r=Gijs
CheckCurrentWord on content process causes sync IPC, so I would like to remove this call on content process. New nsIEditorSpellChecker.suggest method can avoid it. Differential Revision: https://phabricator.services.mozilla.com/D119937
This commit is contained in:
Родитель
a6944a1428
Коммит
49cc605308
|
@ -507,7 +507,7 @@ class ContextMenuChild extends JSWindowActorChild {
|
|||
return false;
|
||||
}
|
||||
|
||||
handleEvent(aEvent) {
|
||||
async handleEvent(aEvent) {
|
||||
contextMenus.set(this.browsingContext, this);
|
||||
|
||||
let defaultPrevented = aEvent.defaultPrevented;
|
||||
|
@ -645,7 +645,6 @@ class ContextMenuChild extends JSWindowActorChild {
|
|||
referrerInfo,
|
||||
editFlags,
|
||||
principal,
|
||||
spellInfo,
|
||||
contentType,
|
||||
docLocation,
|
||||
loginFillInfo,
|
||||
|
@ -692,6 +691,15 @@ class ContextMenuChild extends JSWindowActorChild {
|
|||
// instead.
|
||||
aEvent.stopPropagation();
|
||||
|
||||
data.spellInfo = null;
|
||||
if (!spellInfo) {
|
||||
this.sendAsyncMessage("contextmenu", data);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
data.spellInfo = await spellInfo;
|
||||
} catch (ex) {}
|
||||
this.sendAsyncMessage("contextmenu", data);
|
||||
}
|
||||
|
||||
|
|
|
@ -284,6 +284,10 @@ class nsContextMenu {
|
|||
);
|
||||
}
|
||||
|
||||
if (this.contentData.spellInfo) {
|
||||
this.spellSuggesions = this.contentData.spellInfo.spellSuggestions;
|
||||
}
|
||||
|
||||
if (context.shouldInitInlineSpellCheckerUIWithChildren) {
|
||||
InlineSpellCheckerUI.initFromRemote(
|
||||
this.contentData.spellInfo,
|
||||
|
@ -769,7 +773,7 @@ class nsContextMenu {
|
|||
var numsug = InlineSpellCheckerUI.addSuggestionsToMenu(
|
||||
suggestionsSeparator.parentNode,
|
||||
suggestionsSeparator,
|
||||
5
|
||||
this.spellSuggesions
|
||||
);
|
||||
this.showItem("spell-no-suggestions", numsug == 0);
|
||||
} else {
|
||||
|
|
|
@ -35,13 +35,22 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1272623
|
|||
// Perform the spelling correction
|
||||
let mm = SpecialPowers.loadChromeScript(function() {
|
||||
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
const {BrowserTestUtils} = ChromeUtils.import("resource://testing-common/BrowserTestUtils.jsm");
|
||||
|
||||
// Chrome scripts are run with synchronous messages, so make sure we're completely
|
||||
// decoupled from the content process before doing this work.
|
||||
Cu.dispatch(function() {
|
||||
Cu.dispatch(async function() {
|
||||
let chromeWin = Services.ww.activeWindow;
|
||||
let contextMenu = chromeWin.document.getElementById("contentAreaContextMenu");
|
||||
let suggestion = contextMenu.querySelector(".spell-suggestion");
|
||||
if (!suggestion) {
|
||||
await BrowserTestUtils.waitForMutationCondition(
|
||||
contextMenu,
|
||||
{ childList: true },
|
||||
() => contextMenu.querySelector(".spell-suggestion")
|
||||
);
|
||||
suggestion = contextMenu.querySelector(".spell-suggestion");
|
||||
}
|
||||
suggestion.doCommand();
|
||||
contextMenu.hidePopup();
|
||||
sendAsyncMessage("spellingCorrected");
|
||||
|
|
|
@ -22,7 +22,7 @@ class InlineSpellCheckerChild extends JSWindowActorChild {
|
|||
break;
|
||||
|
||||
case "InlineSpellChecker:replaceMisspelling":
|
||||
InlineSpellCheckerContent.replaceMisspelling(msg.data.index);
|
||||
InlineSpellCheckerContent.replaceMisspelling(msg.data.suggestion);
|
||||
break;
|
||||
|
||||
case "InlineSpellChecker:toggleEnabled":
|
||||
|
|
|
@ -15,8 +15,10 @@ class InlineSpellCheckerParent extends JSWindowActorParent {
|
|||
});
|
||||
}
|
||||
|
||||
replaceMisspelling({ index }) {
|
||||
this.sendAsyncMessage("InlineSpellChecker:replaceMisspelling", { index });
|
||||
replaceMisspelling({ suggestion }) {
|
||||
this.sendAsyncMessage("InlineSpellChecker:replaceMisspelling", {
|
||||
suggestion,
|
||||
});
|
||||
}
|
||||
|
||||
toggleEnabled() {
|
||||
|
|
|
@ -144,7 +144,7 @@
|
|||
|
||||
// suggestion list
|
||||
var suggestionsSeparator = this.getMenuItem("spell-no-suggestions");
|
||||
var numsug = spellui.addSuggestionsToMenu(
|
||||
var numsug = spellui.addSuggestionsToMenuOnParent(
|
||||
event.target,
|
||||
suggestionsSeparator,
|
||||
5
|
||||
|
|
|
@ -62,7 +62,6 @@ InlineSpellChecker.prototype = {
|
|||
this.mOverMisspelling = false;
|
||||
this.mMisspelling = "";
|
||||
this.mMenu = null;
|
||||
this.mSpellSuggestions = [];
|
||||
this.mSuggestionItems = [];
|
||||
this.mDictionaryMenu = null;
|
||||
this.mDictionaryItems = [];
|
||||
|
@ -144,7 +143,40 @@ InlineSpellChecker.prototype = {
|
|||
|
||||
// this prepends up to "maxNumber" suggestions at the given menu position
|
||||
// for the word under the cursor. Returns the number of suggestions inserted.
|
||||
addSuggestionsToMenu(menu, insertBefore, maxNumber) {
|
||||
addSuggestionsToMenuOnParent(menu, insertBefore, maxNumber) {
|
||||
if (this.mRemote) {
|
||||
// This is used on parent process only.
|
||||
// If you want to add suggestions to context menu, get suggestions then
|
||||
// use addSuggestionsToMenu instead.
|
||||
return 0;
|
||||
}
|
||||
if (!this.mInlineSpellChecker || !this.mOverMisspelling) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let spellchecker = this.mInlineSpellChecker.spellChecker;
|
||||
let spellSuggestions = [];
|
||||
|
||||
try {
|
||||
if (!spellchecker.CheckCurrentWord(this.mMisspelling)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (let i = 0; i < maxNumber; i++) {
|
||||
let suggestion = spellchecker.GetSuggestedWord();
|
||||
if (!suggestion.length) {
|
||||
// no more data
|
||||
break;
|
||||
}
|
||||
spellSuggestions.push(suggestion);
|
||||
}
|
||||
} catch (e) {
|
||||
return 0;
|
||||
}
|
||||
return this._addSuggestionsToMenu(menu, insertBefore, spellSuggestions);
|
||||
},
|
||||
|
||||
addSuggestionsToMenu(menu, insertBefore, spellSuggestions) {
|
||||
if (
|
||||
!this.mRemote &&
|
||||
(!this.mInlineSpellChecker || !this.mOverMisspelling)
|
||||
|
@ -152,41 +184,31 @@ InlineSpellChecker.prototype = {
|
|||
return 0;
|
||||
} // nothing to do
|
||||
|
||||
var spellchecker = this.mRemote || this.mInlineSpellChecker.spellChecker;
|
||||
try {
|
||||
if (!this.mRemote && !spellchecker.CheckCurrentWord(this.mMisspelling)) {
|
||||
return 0;
|
||||
} // word seems not misspelled after all (?)
|
||||
} catch (e) {
|
||||
if (!spellSuggestions?.length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return this._addSuggestionsToMenu(menu, insertBefore, spellSuggestions);
|
||||
},
|
||||
|
||||
_addSuggestionsToMenu(menu, insertBefore, spellSuggestions) {
|
||||
this.mMenu = menu;
|
||||
this.mSpellSuggestions = [];
|
||||
this.mSuggestionItems = [];
|
||||
for (var i = 0; i < maxNumber; i++) {
|
||||
var suggestion = spellchecker.GetSuggestedWord();
|
||||
if (!suggestion.length) {
|
||||
break;
|
||||
}
|
||||
this.mSpellSuggestions.push(suggestion);
|
||||
|
||||
for (let suggestion of spellSuggestions) {
|
||||
var item = menu.ownerDocument.createXULElement("menuitem");
|
||||
this.mSuggestionItems.push(item);
|
||||
item.setAttribute("label", suggestion);
|
||||
item.setAttribute("value", suggestion);
|
||||
// this function thing is necessary to generate a callback with the
|
||||
// correct binding of "val" (the index in this loop).
|
||||
var callback = function(me, val) {
|
||||
return function(evt) {
|
||||
me.replaceMisspelling(val);
|
||||
};
|
||||
};
|
||||
item.addEventListener("command", callback(this, i), true);
|
||||
item.addEventListener(
|
||||
"command",
|
||||
this.replaceMisspelling.bind(this, suggestion),
|
||||
true
|
||||
);
|
||||
item.setAttribute("class", "spell-suggestion");
|
||||
menu.insertBefore(item, insertBefore);
|
||||
}
|
||||
return this.mSpellSuggestions.length;
|
||||
return spellSuggestions.length;
|
||||
},
|
||||
|
||||
// undoes the work of addSuggestionsToMenu for the same menu
|
||||
|
@ -301,21 +323,18 @@ InlineSpellChecker.prototype = {
|
|||
},
|
||||
|
||||
// callback for selecting a suggested replacement
|
||||
replaceMisspelling(index) {
|
||||
replaceMisspelling(suggestion) {
|
||||
if (this.mRemote) {
|
||||
this.mRemote.replaceMisspelling(index);
|
||||
this.mRemote.replaceMisspelling(suggestion);
|
||||
return;
|
||||
}
|
||||
if (!this.mInlineSpellChecker || !this.mOverMisspelling) {
|
||||
return;
|
||||
}
|
||||
if (index < 0 || index >= this.mSpellSuggestions.length) {
|
||||
return;
|
||||
}
|
||||
this.mInlineSpellChecker.replaceWord(
|
||||
this.mWordNode,
|
||||
this.mWordOffset,
|
||||
this.mSpellSuggestions[index]
|
||||
suggestion
|
||||
);
|
||||
},
|
||||
|
||||
|
@ -514,22 +533,8 @@ RemoteSpellChecker.prototype = {
|
|||
get enableRealTimeSpell() {
|
||||
return this._spellInfo.enableRealTimeSpell;
|
||||
},
|
||||
|
||||
GetSuggestedWord() {
|
||||
if (!this._suggestionGenerator) {
|
||||
this._suggestionGenerator = (function*(spellInfo) {
|
||||
for (let i of spellInfo.spellSuggestions) {
|
||||
yield i;
|
||||
}
|
||||
})(this._spellInfo);
|
||||
}
|
||||
|
||||
let next = this._suggestionGenerator.next();
|
||||
if (next.done) {
|
||||
this._suggestionGenerator = null;
|
||||
return "";
|
||||
}
|
||||
return next.value;
|
||||
get suggestions() {
|
||||
return this._spellInfo.spellSuggestions;
|
||||
},
|
||||
|
||||
get currentDictionary() {
|
||||
|
@ -543,8 +548,8 @@ RemoteSpellChecker.prototype = {
|
|||
this._actor.selectDictionary({ localeCode });
|
||||
},
|
||||
|
||||
replaceMisspelling(index) {
|
||||
this._actor.replaceMisspelling({ index });
|
||||
replaceMisspelling(suggestion) {
|
||||
this._actor.replaceMisspelling({ suggestion });
|
||||
},
|
||||
|
||||
toggleEnabled() {
|
||||
|
|
|
@ -15,7 +15,7 @@ var InlineSpellCheckerContent = {
|
|||
_spellChecker: null,
|
||||
_actor: null,
|
||||
|
||||
initContextMenu(event, editFlags, actor) {
|
||||
async initContextMenu(event, editFlags, actor) {
|
||||
this._actor = actor;
|
||||
this._actor.registerDestructionObserver(this);
|
||||
|
||||
|
@ -62,6 +62,7 @@ var InlineSpellCheckerContent = {
|
|||
|
||||
let realSpellChecker = spellChecker.mInlineSpellChecker.spellChecker;
|
||||
let dictionaryList = realSpellChecker.GetDictionaryList();
|
||||
let spellSuggestions = await this._generateSpellSuggestions();
|
||||
|
||||
return {
|
||||
canSpellCheck: spellChecker.canSpellCheck,
|
||||
|
@ -69,7 +70,7 @@ var InlineSpellCheckerContent = {
|
|||
enableRealTimeSpell: spellChecker.enabled,
|
||||
overMisspelling: spellChecker.overMisspelling,
|
||||
misspelling: spellChecker.mMisspelling,
|
||||
spellSuggestions: this._generateSpellSuggestions(),
|
||||
spellSuggestions,
|
||||
currentDictionary: spellChecker.mInlineSpellChecker.spellChecker.GetCurrentDictionary(),
|
||||
dictionaryList,
|
||||
};
|
||||
|
@ -87,24 +88,18 @@ var InlineSpellCheckerContent = {
|
|||
this.uninitContextMenu();
|
||||
},
|
||||
|
||||
_generateSpellSuggestions() {
|
||||
async _generateSpellSuggestions() {
|
||||
let spellChecker = this._spellChecker.mInlineSpellChecker.spellChecker;
|
||||
let suggestions = null;
|
||||
try {
|
||||
spellChecker.CheckCurrentWord(this._spellChecker.mMisspelling);
|
||||
suggestions = await spellChecker.suggest(
|
||||
this._spellChecker.mMisspelling,
|
||||
5
|
||||
);
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let suggestions = new Array(5);
|
||||
for (let i = 0; i < 5; ++i) {
|
||||
suggestions[i] = spellChecker.GetSuggestedWord();
|
||||
if (suggestions[i].length === 0) {
|
||||
suggestions.length = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this._spellChecker.mSpellSuggestions = suggestions;
|
||||
return suggestions;
|
||||
},
|
||||
|
||||
|
@ -112,8 +107,8 @@ var InlineSpellCheckerContent = {
|
|||
this._spellChecker.selectDictionary(localeCode);
|
||||
},
|
||||
|
||||
replaceMisspelling(index) {
|
||||
this._spellChecker.replaceMisspelling(index);
|
||||
replaceMisspelling(suggestion) {
|
||||
this._spellChecker.replaceMisspelling(suggestion);
|
||||
},
|
||||
|
||||
toggleEnabled() {
|
||||
|
|
Загрузка…
Ссылка в новой задаче