Bug 1454373 - Switch protocol.js to native promises. r=jryans
authorAlexandre Poirot <poirot.alex@gmail.com>
Fri, 13 Apr 2018 14:34:12 -0700
changeset 467766 cde33317ae7ae625f4231372ad7ad122df77d0ba
parent 467682 79b7ee8b01ee122b3f7122f926e5ae9dc1132a96
child 467767 0acfc9ae925d995df2fe38c2c64a99ab93079e83
push id9165
push userasasaki@mozilla.com
push dateThu, 26 Apr 2018 21:04:54 +0000
treeherdermozilla-beta@064c3804de2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjryans
bugs1454373
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1454373 - Switch protocol.js to native promises. r=jryans MozReview-Commit-ID: ALifNayHJJG
devtools/server/tests/unit/test_protocol_stack.js
devtools/shared/defer.js
devtools/shared/protocol.js
--- a/devtools/server/tests/unit/test_protocol_stack.js
+++ b/devtools/server/tests/unit/test_protocol_stack.js
@@ -71,17 +71,17 @@ function run_test() {
 
   client.connect().then(function onConnect() {
     rootClient = RootFront(client);
 
     rootClient.simpleReturn().then(() => {
       let stack = Components.stack;
       while (stack) {
         info(stack.name);
-        if (stack.name == "onConnect") {
+        if (stack.name.includes("run_test/onConnect")) {
           // Reached back to outer function before request
           ok(true, "Complete stack");
           return;
         }
         stack = stack.asyncCaller || stack.caller;
       }
       ok(false, "Incomplete stack");
     }, () => {
--- a/devtools/shared/defer.js
+++ b/devtools/shared/defer.js
@@ -1,15 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
-// See bug 1273941 to understand this choice of promise.
+// We have to keep using Promise.jsm here, because DOM Promises
+// start freezing during panel iframes destruction.
+// More info in bug 1454373 comment 15.
 const Promise = require("promise");
 
 /**
  * Returns a deferred object, with a resolve and reject property.
  * https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Promise.jsm/Deferred
  */
 module.exports = function defer() {
   let resolve, reject;
--- a/devtools/shared/protocol.js
+++ b/devtools/shared/protocol.js
@@ -1,22 +1,35 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
-var promise = require("promise");
-var defer = require("devtools/shared/defer");
 const { extend } = require("devtools/shared/extend");
 var EventEmitter = require("devtools/shared/event-emitter");
 var {getStack, callFunctionWithAsyncStack} = require("devtools/shared/platform/stack");
 var {settleAll} = require("devtools/shared/DevToolsUtils");
 var {lazyLoadSpec, lazyLoadFront} = require("devtools/shared/specs/index");
 
+// Bug 1454373: devtools/shared/defer still uses Promise.jsm which is slower
+// than DOM Promises. So implement our own copy of `defer` based on DOM Promises.
+function defer() {
+  let resolve, reject;
+  let promise = new Promise(function() {
+    resolve = arguments[0];
+    reject = arguments[1];
+  });
+  return {
+    resolve: resolve,
+    reject: reject,
+    promise: promise
+  };
+}
+
 /**
  * Types: named marshallers/demarshallers.
  *
  * Types provide a 'write' function that takes a js representation and
  * returns a protocol representation, and a "read" function that
  * takes a protocol representation and returns a js representation.
  *
  * The read and write methods are also passed a context object that
@@ -978,17 +991,17 @@ Actor.prototype = extend(Pool.prototype,
     this.conn.send({
       from: this.actorID,
       error: error.error || "unknownError",
       message: error.message
     });
   },
 
   _queueResponse: function(create) {
-    let pending = this._pendingResponse || promise.resolve(null);
+    let pending = this._pendingResponse || Promise.resolve(null);
     let response = create(pending);
     this._pendingResponse = response;
   }
 });
 exports.Actor = Actor;
 
 /**
  * Tags a prtotype method as an actor method implementation.
@@ -1243,17 +1256,17 @@ Front.prototype = extend(Pool.prototype,
     return Pool.prototype.manage.call(this, front);
   },
 
   /**
    * @returns a promise that will resolve to the actorID this front
    * represents.
    */
   actor: function() {
-    return promise.resolve(this.actorID);
+    return Promise.resolve(this.actorID);
   },
 
   toString: function() {
     return "[Front for " + this.typeName + "/" + this.actorID + "]";
   },
 
   /**
    * Update the actor from its representation.
@@ -1309,17 +1322,17 @@ Front.prototype = extend(Pool.prototype,
         throw ex;
       }
       if (event.pre) {
         let results = event.pre.map(pre => pre.apply(this, args));
 
         // Check to see if any of the preEvents returned a promise -- if so,
         // wait for their resolution before emitting. Otherwise, emit synchronously.
         if (results.some(result => result && typeof result.then === "function")) {
-          promise.all(results).then(() => {
+          Promise.all(results).then(() => {
             return EventEmitter.emit.apply(null, [this, event.name].concat(args));
           });
           return;
         }
       }
 
       EventEmitter.emit.apply(null, [this, event.name].concat(args));
       return;