зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1126350 - Settle all toolbox destruction before final cleanup. r=pbrosset
This commit is contained in:
Родитель
e5bb515f47
Коммит
925318d2b4
|
@ -47,6 +47,7 @@ loader.lazyGetter(this, "toolboxStrings", () => {
|
|||
|
||||
loader.lazyGetter(this, "Selection", () => require("devtools/framework/selection").Selection);
|
||||
loader.lazyGetter(this, "InspectorFront", () => require("devtools/server/actors/inspector").InspectorFront);
|
||||
loader.lazyRequireGetter(this, "DevToolsUtils", "devtools/toolkit/DevToolsUtils");
|
||||
|
||||
// White-list buttons that can be toggled to prevent adding prefs for
|
||||
// addons that have manually inserted toolbarbuttons into DOM.
|
||||
|
@ -1659,8 +1660,11 @@ Toolbox.prototype = {
|
|||
// Finish all outstanding tasks (which means finish destroying panels and
|
||||
// then destroying the host, successfully or not) before destroying the
|
||||
// target.
|
||||
this._destroyer = promise.all(outstanding)
|
||||
.then(() => this.destroyHost()).then(null, console.error).then(() => {
|
||||
this._destroyer = DevToolsUtils.settleAll(outstanding)
|
||||
.catch(console.error)
|
||||
.then(() => this.destroyHost())
|
||||
.catch(console.error)
|
||||
.then(() => {
|
||||
// Targets need to be notified that the toolbox is being torn down.
|
||||
// This is done after other destruction tasks since it may tear down
|
||||
// fronts and the debugger transport which earlier destroy methods may
|
||||
|
|
|
@ -568,3 +568,76 @@ function convertToUnicode(aString, aCharset=null) {
|
|||
return aString;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a promise that is resolved or rejected when all promises have settled
|
||||
* (resolved or rejected).
|
||||
*
|
||||
* This differs from Promise.all, which will reject immediately after the first
|
||||
* rejection, instead of waiting for the remaining promises to settle.
|
||||
*
|
||||
* @param values
|
||||
* Iterable of promises that may be pending, resolved, or rejected. When
|
||||
* when all promises have settled (resolved or rejected), the returned
|
||||
* promise will be resolved or rejected as well.
|
||||
*
|
||||
* @return A new promise that is fulfilled when all values have settled
|
||||
* (resolved or rejected). Its resolution value will be an array of all
|
||||
* resolved values in the given order, or undefined if values is an
|
||||
* empty array. The reject reason will be forwarded from the first
|
||||
* promise in the list of given promises to be rejected.
|
||||
*/
|
||||
exports.settleAll = values => {
|
||||
if (values === null || typeof(values[Symbol.iterator]) != "function") {
|
||||
throw new Error("settleAll() expects an iterable.");
|
||||
}
|
||||
|
||||
let deferred = promise.defer();
|
||||
|
||||
values = Array.isArray(values) ? values : [...values];
|
||||
let countdown = values.length;
|
||||
let resolutionValues = new Array(countdown);
|
||||
let rejectionValue;
|
||||
let rejectionOccurred = false;
|
||||
|
||||
if (!countdown) {
|
||||
deferred.resolve(resolutionValues);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function checkForCompletion() {
|
||||
if (--countdown > 0) {
|
||||
return;
|
||||
}
|
||||
if (!rejectionOccurred) {
|
||||
deferred.resolve(resolutionValues);
|
||||
} else {
|
||||
deferred.reject(rejectionValue);
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
let index = i;
|
||||
let value = values[i];
|
||||
let resolver = result => {
|
||||
resolutionValues[index] = result;
|
||||
checkForCompletion();
|
||||
};
|
||||
let rejecter = error => {
|
||||
if (!rejectionOccurred) {
|
||||
rejectionValue = error;
|
||||
rejectionOccurred = true;
|
||||
}
|
||||
checkForCompletion();
|
||||
};
|
||||
|
||||
if (value && typeof(value.then) == "function") {
|
||||
value.then(resolver, rejecter);
|
||||
} else {
|
||||
// Given value is not a promise, forward it as a resolution value.
|
||||
resolver(value);
|
||||
}
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче