зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1367505 - Set and clear pseudo-class locks all at once to avoid restyle thrashing when sending select options to parent process. r=jaws
This removes nearly half of the time spent in the child process pause in bug 1118086. (On my laptop, it cuts the child process pause from about 1560ms to 860ms; the parent process pause is still just over 5 seconds.) Using querySelectorAll to find only the options that need to be locked is much faster than iterating over them and locking all of them both because the iteration is slow and the locking is somewhat slow even when it's a no-op. MozReview-Commit-ID: 17h3WIt9c2O --HG-- extra : transplant_source : %A2H%DC%8A%CF%CFI%B0%D5%D2%05%1B6%B6%B1o%89%98D%1B
This commit is contained in:
Родитель
31beca4070
Коммит
e9acd732ee
|
@ -43,6 +43,8 @@ this.SelectContentHelper = function(aElement, aOptions, aGlobal) {
|
|||
this._uaSelectBackgroundColor = null;
|
||||
this._uaSelectColor = null;
|
||||
this._closeAfterBlur = true;
|
||||
this._pseudoStylesSetup = false;
|
||||
this._lockedDescendants = null;
|
||||
this.init();
|
||||
this.showDropDown();
|
||||
this._updateTimer = new DeferredTask(this._update.bind(this), 0);
|
||||
|
@ -100,13 +102,12 @@ this.SelectContentHelper.prototype = {
|
|||
|
||||
showDropDown() {
|
||||
this.element.openInParentProcess = true;
|
||||
this._setupPseudoClassStyles();
|
||||
let rect = this._getBoundingContentRect();
|
||||
DOMUtils.addPseudoClassLock(this.element, ":focus");
|
||||
let computedStyles = getComputedStyles(this.element);
|
||||
this._selectBackgroundColor = computedStyles.backgroundColor;
|
||||
this._selectColor = computedStyles.color;
|
||||
this._selectTextShadow = computedStyles.textShadow;
|
||||
DOMUtils.clearPseudoClassLocks(this.element);
|
||||
this.global.sendAsyncMessage("Forms:ShowDropDown", {
|
||||
direction: computedStyles.direction,
|
||||
isOpenedViaTouch: this.isOpenedViaTouch,
|
||||
|
@ -121,18 +122,52 @@ this.SelectContentHelper.prototype = {
|
|||
uaSelectBackgroundColor: this.uaSelectBackgroundColor,
|
||||
uaSelectColor: this.uaSelectColor
|
||||
});
|
||||
this._clearPseudoClassStyles();
|
||||
gOpen = true;
|
||||
},
|
||||
|
||||
_setupPseudoClassStyles() {
|
||||
if (this._pseudoStylesSetup) {
|
||||
throw new Error("pseudo styles must not be set up yet");
|
||||
}
|
||||
// Do all of the things that change style at once, before we read
|
||||
// any styles.
|
||||
this._pseudoStylesSetup = true;
|
||||
DOMUtils.addPseudoClassLock(this.element, ":focus");
|
||||
let lockedDescendants = this._lockedDescendants = this.element.querySelectorAll(":checked");
|
||||
for (let child of lockedDescendants) {
|
||||
// Selected options have the :checked pseudo-class, which
|
||||
// we want to disable before calculating the computed
|
||||
// styles since the user agent styles alter the styling
|
||||
// based on :checked.
|
||||
DOMUtils.addPseudoClassLock(child, ":checked", false);
|
||||
}
|
||||
},
|
||||
|
||||
_clearPseudoClassStyles() {
|
||||
if (!this._pseudoStylesSetup) {
|
||||
throw new Error("pseudo styles must be set up already");
|
||||
}
|
||||
// Undo all of the things that change style at once, after we're
|
||||
// done reading styles.
|
||||
DOMUtils.clearPseudoClassLocks(this.element);
|
||||
let lockedDescendants = this._lockedDescendants;
|
||||
for (let child of lockedDescendants) {
|
||||
DOMUtils.clearPseudoClassLocks(child);
|
||||
}
|
||||
this._lockedDescendants = null;
|
||||
this._pseudoStylesSetup = false;
|
||||
},
|
||||
|
||||
_getBoundingContentRect() {
|
||||
return BrowserUtils.getElementBoundingScreenRect(this.element);
|
||||
},
|
||||
|
||||
_buildOptionList() {
|
||||
DOMUtils.addPseudoClassLock(this.element, ":focus");
|
||||
let result = buildOptionListForChildren(this.element);
|
||||
DOMUtils.clearPseudoClassLocks(this.element);
|
||||
return result;
|
||||
if (!this._pseudoStylesSetup) {
|
||||
throw new Error("pseudo styles must be set up");
|
||||
}
|
||||
return buildOptionListForChildren(this.element);
|
||||
},
|
||||
|
||||
_update() {
|
||||
|
@ -141,12 +176,11 @@ this.SelectContentHelper.prototype = {
|
|||
// Technically we might not need to set this pseudo-class
|
||||
// during _update() since the element should organically
|
||||
// have :focus, though it is here for belt-and-suspenders.
|
||||
DOMUtils.addPseudoClassLock(this.element, ":focus");
|
||||
this._setupPseudoClassStyles();
|
||||
let computedStyles = getComputedStyles(this.element);
|
||||
this._selectBackgroundColor = computedStyles.backgroundColor;
|
||||
this._selectColor = computedStyles.color;
|
||||
this._selectTextShadow = computedStyles.textShadow;
|
||||
DOMUtils.clearPseudoClassLocks(this.element);
|
||||
this.global.sendAsyncMessage("Forms:UpdateDropDown", {
|
||||
options: this._buildOptionList(),
|
||||
selectedIndex: this.element.selectedIndex,
|
||||
|
@ -158,6 +192,7 @@ this.SelectContentHelper.prototype = {
|
|||
uaSelectBackgroundColor: this.uaSelectBackgroundColor,
|
||||
uaSelectColor: this.uaSelectColor
|
||||
});
|
||||
this._clearPseudoClassStyles();
|
||||
},
|
||||
|
||||
// Determine user agent background-color and color.
|
||||
|
@ -344,11 +379,6 @@ function buildOptionListForChildren(node) {
|
|||
textContent = "";
|
||||
}
|
||||
|
||||
// Selected options have the :checked pseudo-class, which
|
||||
// we want to disable before calculating the computed
|
||||
// styles since the user agent styles alter the styling
|
||||
// based on :checked.
|
||||
DOMUtils.addPseudoClassLock(child, ":checked", false);
|
||||
let cs = getComputedStyles(child);
|
||||
|
||||
let info = {
|
||||
|
@ -370,10 +400,6 @@ function buildOptionListForChildren(node) {
|
|||
info.textShadow = cs.textShadow;
|
||||
}
|
||||
|
||||
// We must wait until all computedStyles have been
|
||||
// read before we clear the locks.
|
||||
DOMUtils.clearPseudoClassLocks(child);
|
||||
|
||||
result.push(info);
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче