Bug 1305194 - wait a little longer when the finder iterator is requested to find a query of only one or two characters, which improves usability due to less flickering of highlighter results and performance due to avoiding the most costly nsFind operations there are on a page. r=jaws

Single and double character find operations cause a big hit on nsFind, because
it usually yields many more occurrences than other queries. But most importantly,
it needs to keep iterating each text node much longer than other queries, because
there is much less escapes/ loop exits happening.
This also fixes the FinderIterator infinite-depth call-stack due to unresolved
promises that remain active during the lifetime of the FinderIterator. Unwinding
the call-stack properly should save us bytes from the heap.

MozReview-Commit-ID: 4K19X0yngC7

--HG--
extra : rebase_source : 1801dc16736d0ff9c7534bdaf3ec5a73b326f244
This commit is contained in:
Mike de Boer 2016-10-12 15:46:44 +02:00
Родитель 7e35d12742
Коммит da36d08c94
3 изменённых файлов: 42 добавлений и 9 удалений

Просмотреть файл

@ -31,7 +31,7 @@
const SAMPLE_TEXT = "Some text in a text field.";
const SEARCH_TEXT = "Text Test";
const NOT_FOUND_TEXT = "This text is not on the page."
const ITERATOR_TIMEOUT = gPrefsvc.getIntPref("findbar.iteratorTimeout") + 20;
const ITERATOR_TIMEOUT = gPrefsvc.getIntPref("findbar.iteratorTimeout");
var gFindBar = null;
var gBrowser;
@ -255,7 +255,7 @@
};
gFindBar.browser.finder.addResultListener(listener);
// Make sure we resolve _at least_ after five times the find iterator timeout.
setTimeout(resolve, ITERATOR_TIMEOUT * 5);
setTimeout(resolve, (ITERATOR_TIMEOUT * 5) + 20);
});
}
@ -523,7 +523,7 @@
if (matchCase.checked) {
promise = promiseFindResult();
matchCase.click();
yield new Promise(resolve => setTimeout(resolve, ITERATOR_TIMEOUT));
yield new Promise(resolve => setTimeout(resolve, ITERATOR_TIMEOUT + 20));
yield promise;
}
@ -558,7 +558,13 @@
gFindBar._findField.select();
gFindBar._findField.focus();
yield new Promise(resolve => setTimeout(resolve, ITERATOR_TIMEOUT));
let timeout = ITERATOR_TIMEOUT;
if (test.text.length == 1)
timeout *= 4;
else if (test.text.length == 2)
timeout *= 2;
timeout += 20;
yield new Promise(resolve => setTimeout(resolve, timeout));
yield enterStringIntoFindField(test.text, false);
yield promiseMatchesCountResult();
let matches = foundMatches.value.match(regex);
@ -567,7 +573,7 @@
} else {
assertMatches(test, matches);
for (let i = 1; i < test.total; i++) {
yield new Promise(resolve => setTimeout(resolve, ITERATOR_TIMEOUT));
yield new Promise(resolve => setTimeout(resolve, timeout));
gFindBar.onFindAgainCommand();
yield promiseMatchesCountResult();
// test.current + 1, test.current + 2, ..., test.total, 1, ..., test.current
@ -659,7 +665,7 @@
let result = yield promise;
is(result.result, Ci.nsITypeAheadFind.FIND_FOUND, "Text should be found");
yield new Promise(resolve => setTimeout(resolve, ITERATOR_TIMEOUT));
yield new Promise(resolve => setTimeout(resolve, ITERATOR_TIMEOUT + 20));
promise = promiseFindResult();
let check = gFindBar.getElement("find-entire-word");
check.click();

Просмотреть файл

@ -170,6 +170,10 @@ this.FinderIterator = {
clearTimeout(this._timer);
this._timer = null;
}
if (this._runningFindResolver) {
this._runningFindResolver();
this._runningFindResolver = null;
}
if (cachePrevious) {
this._previousRanges = [].concat(this.ranges);
@ -220,6 +224,10 @@ this.FinderIterator = {
clearTimeout(this._timer);
this._timer = null;
}
if (this._runningFindResolver) {
this._runningFindResolver();
this._runningFindResolver = null;
}
this._catchingUp.clear();
this._currentParams = this._previousParams = null;
@ -421,8 +429,22 @@ this.FinderIterator = {
if (this._timeout) {
if (this._timer)
clearTimeout(this._timer);
yield new Promise(resolve => this._timer = setTimeout(resolve, this._timeout));
this._timer = null;
if (this._runningFindResolver)
this._runningFindResolver();
let timeout = this._timeout;
let searchTerm = this._currentParams.word;
// Wait a little longer when the first or second character is typed into
// the findbar.
if (searchTerm.length == 1)
timeout *= 4;
else if (searchTerm.length == 2)
timeout *= 2;
yield new Promise(resolve => {
this._runningFindResolver = resolve;
this._timer = setTimeout(resolve, timeout);
});
this._timer = this._runningFindResolver = null;
// During the timeout, we could have gotten the signal to stop iterating.
// Make sure we do here.
if (!this.running || spawnId !== this._spawnId)

Просмотреть файл

@ -221,7 +221,12 @@ add_task(function* testModalResults() {
yield promiseOpenFindbar(findbar);
Assert.ok(!findbar.hidden, "Findbar should be open now.");
yield new Promise(resolve => setTimeout(resolve, kIteratorTimeout));
let timeout = kIteratorTimeout;
if (word.length == 1)
timeout *= 4;
else if (word.length == 2)
timeout *= 2;
yield new Promise(resolve => setTimeout(resolve, timeout));
let promise = promiseTestHighlighterOutput(browser, word, expectedResult,
expectedResult.extraTest);
yield promiseEnterStringIntoFindField(findbar, word);