diff --git a/devtools/client/animationinspector/animation-controller.js b/devtools/client/animationinspector/animation-controller.js index e5ad109223a..cc68a600d72 100644 --- a/devtools/client/animationinspector/animation-controller.js +++ b/devtools/client/animationinspector/animation-controller.js @@ -144,6 +144,13 @@ var AnimationsController = { // Expose actor capabilities. this.traits = yield getServerTraits(target); + // We want to handle animation mutation events synchronously to avoid race + // conditions when there are many rapid mutations. So when a mutation occurs + // and animations are removed, we don't release the corresponding actors + // in a blocking way, we just release asynchronously and don't wait for + // completion, but instead store the promise in this array. + this.nonBlockingPlayerReleases = []; + if (this.destroyed) { console.warn("Could not fully initialize the AnimationsController"); return; @@ -176,6 +183,9 @@ var AnimationsController = { yield this.destroyAnimationPlayers(); this.nodeFront = null; + // Finish releasing players that haven't been released yet. + yield Promise.all(this.nonBlockingPlayerReleases); + if (this.animationsFront) { this.animationsFront.destroy(); this.animationsFront = null; @@ -331,7 +341,7 @@ var AnimationsController = { } }), - onAnimationMutations: Task.async(function*(changes) { + onAnimationMutations: function(changes) { // Insert new players into this.animationPlayers when new animations are // added. for (let {type, player} of changes) { @@ -340,7 +350,8 @@ var AnimationsController = { } if (type === "removed") { - yield player.release(); + // Don't wait for the release request to complete, we can do that later. + this.nonBlockingPlayerReleases.push(player.release()); let index = this.animationPlayers.indexOf(player); this.animationPlayers.splice(index, 1); } @@ -348,7 +359,7 @@ var AnimationsController = { // Let the UI know the list has been updated. this.emit(this.PLAYERS_UPDATED_EVENT, this.animationPlayers); - }), + }, /** * Get the latest known current time of document.timeline.