Bug 1436978 - Stop using Promise.jsm in devtools/server in favor of DOM Promises. r=jdescottes draft
authorAlexandre Poirot <poirot.alex@gmail.com>
Tue, 13 Feb 2018 02:31:14 -0800
changeset 754793 a08ed11b9ad3e028930bc77d24d73bc8568011e9
parent 754572 e43f2f6ea111c2d059d95fa9a71516b869a69698
child 754794 a84a8e10305fedd61f03b11ab75086a3e54ac68b
push id99001
push userbmo:poirot.alex@gmail.com
push dateWed, 14 Feb 2018 10:14:19 +0000
reviewersjdescottes
bugs1436978
milestone60.0a1
Bug 1436978 - Stop using Promise.jsm in devtools/server in favor of DOM Promises. r=jdescottes MozReview-Commit-ID: Hv7uYZKZGIO
devtools/server/actors/animation.js
devtools/server/actors/common.js
devtools/server/actors/inspector/utils.js
devtools/server/actors/source.js
devtools/server/actors/storage.js
devtools/server/actors/string.js
devtools/server/actors/styles.js
devtools/server/actors/stylesheets.js
devtools/server/actors/thread.js
devtools/server/actors/utils/TabSources.js
devtools/server/actors/webbrowser.js
devtools/server/performance/recorder.js
devtools/server/tests/mochitest/inspector-helpers.js
devtools/server/tests/mochitest/test_inspector-mutations-childlist.html
devtools/server/tests/mochitest/test_inspector-resize.html
devtools/server/tests/mochitest/test_inspector-retain.html
devtools/server/tests/mochitest/test_inspector-search-front.html
devtools/server/tests/mochitest/test_inspector-search.html
devtools/server/tests/mochitest/test_inspector-traversal.html
devtools/server/tests/unit/head_dbg.js
devtools/server/tests/unit/test_blackboxing-06.js
devtools/server/tests/unit/test_protocol_async.js
devtools/server/tests/unit/test_protocol_children.js
devtools/server/tests/unit/test_protocol_simple.js
devtools/server/tests/unit/test_sourcemaps-10.js
devtools/server/tests/unit/test_sourcemaps-11.js
--- a/devtools/server/actors/animation.js
+++ b/devtools/server/actors/animation.js
@@ -21,17 +21,16 @@
  * References:
  * - WebAnimation spec:
  *   http://drafts.csswg.org/web-animations/
  * - WebAnimation WebIDL files:
  *   /dom/webidl/Animation*.webidl
  */
 
 const {Cu, Ci} = require("chrome");
-const promise = require("promise");
 const protocol = require("devtools/shared/protocol");
 const {Actor} = protocol;
 const {animationPlayerSpec, animationsSpec} = require("devtools/shared/specs/animation");
 
 // Types of animations.
 const ANIMATION_TYPES = {
   CSS_ANIMATION: "cssanimation",
   CSS_TRANSITION: "csstransition",
@@ -808,64 +807,64 @@ exports.AnimationsActor = protocol.Actor
     // Until the WebAnimations API provides a way to play/pause via the document
     // timeline, we have to iterate through the whole DOM to find all players.
     for (let player of
          this.getAllAnimations(this.tabActor.window.document, true)) {
       player.pause();
       readyPromises.push(player.ready);
     }
     this.allAnimationsPaused = true;
-    return promise.all(readyPromises);
+    return Promise.all(readyPromises);
   },
 
   /**
    * Play all animations in the current tabActor's frames.
    * This method only returns when animations have left their pending states.
    */
   playAll: function () {
     let readyPromises = [];
     // Until the WebAnimations API provides a way to play/pause via the document
     // timeline, we have to iterate through the whole DOM to find all players.
     for (let player of
          this.getAllAnimations(this.tabActor.window.document, true)) {
       player.play();
       readyPromises.push(player.ready);
     }
     this.allAnimationsPaused = false;
-    return promise.all(readyPromises);
+    return Promise.all(readyPromises);
   },
 
   toggleAll: function () {
     if (this.allAnimationsPaused) {
       return this.playAll();
     }
     return this.pauseAll();
   },
 
   /**
    * Toggle (play/pause) several animations at the same time.
    * @param {Array} players A list of AnimationPlayerActor objects.
    * @param {Boolean} shouldPause If set to true, the players will be paused,
    * otherwise they will be played.
    */
   toggleSeveral: function (players, shouldPause) {
-    return promise.all(players.map(player => {
+    return Promise.all(players.map(player => {
       return shouldPause ? player.pause() : player.play();
     }));
   },
 
   /**
    * Set the current time of several animations at the same time.
    * @param {Array} players A list of AnimationPlayerActor.
    * @param {Number} time The new currentTime.
    * @param {Boolean} shouldPause Should the players be paused too.
    */
   setCurrentTimes: function (players, time, shouldPause) {
-    return promise.all(players.map(player => {
-      let pause = shouldPause ? player.pause() : promise.resolve();
+    return Promise.all(players.map(player => {
+      let pause = shouldPause ? player.pause() : Promise.resolve();
       return pause.then(() => player.setCurrentTime(time));
     }));
   },
 
   /**
    * Set the playback rate of several animations at the same time.
    * @param {Array} players A list of AnimationPlayerActor.
    * @param {Number} rate The new rate.
--- a/devtools/server/actors/common.js
+++ b/devtools/server/actors/common.js
@@ -1,17 +1,16 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* 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";
 
-const promise = require("promise");
 const { method } = require("devtools/shared/protocol");
 
 /**
  * Creates "registered" actors factory meant for creating another kind of
  * factories, ObservedActorFactory, during the call to listTabs.
  * These factories live in DebuggerServer.{tab|global}ActorFactories.
  *
  * These actors only exposes:
@@ -482,17 +481,17 @@ exports.GeneratedLocation = GeneratedLoc
  *          The decorated method.
  */
 function expectState(expectedState, methodFunc, activity) {
   return function (...args) {
     if (this.state !== expectedState) {
       const msg = `Wrong state while ${activity}:` +
                   `Expected '${expectedState}', ` +
                   `but current state is '${this.state}'.`;
-      return promise.reject(new Error(msg));
+      return Promise.reject(new Error(msg));
     }
 
     return methodFunc.apply(this, args);
   };
 }
 
 exports.expectState = expectState;
 
--- a/devtools/server/actors/inspector/utils.js
+++ b/devtools/server/actors/inspector/utils.js
@@ -1,17 +1,16 @@
 /* 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";
 
 const {Ci, Cu} = require("chrome");
 
-const promise = require("promise");
 const {Task} = require("devtools/shared/task");
 
 loader.lazyRequireGetter(this, "AsyncUtils", "devtools/shared/async-utils");
 loader.lazyRequireGetter(this, "flags", "devtools/shared/flags");
 loader.lazyRequireGetter(this, "DevToolsUtils", "devtools/shared/DevToolsUtils");
 loader.lazyRequireGetter(this, "nodeFilterConstants", "devtools/shared/dom-node-filter-constants");
 
 loader.lazyRequireGetter(this, "isNativeAnonymous", "devtools/shared/layout/utils", true);
@@ -135,44 +134,44 @@ function nodeHasSize(node) {
  * before the waiting is aborted. Ignored if flags.testing is set.
  *
  * @return {Promise} that is fulfilled once the image has loaded. If the image
  * fails to load or the load takes too long, the promise is rejected.
  */
 function ensureImageLoaded(image, timeout) {
   let { HTMLImageElement } = image.ownerGlobal;
   if (!(image instanceof HTMLImageElement)) {
-    return promise.reject("image must be an HTMLImageELement");
+    return Promise.reject("image must be an HTMLImageELement");
   }
 
   if (image.complete) {
     // The image has already finished loading.
-    return promise.resolve();
+    return Promise.resolve();
   }
 
   // This image is still loading.
   let onLoad = AsyncUtils.listenOnce(image, "load");
 
   // Reject if loading fails.
   let onError = AsyncUtils.listenOnce(image, "error").then(() => {
-    return promise.reject("Image '" + image.src + "' failed to load.");
+    return Promise.reject("Image '" + image.src + "' failed to load.");
   });
 
   // Don't timeout when testing. This is never settled.
   let onAbort = new Promise(() => {});
 
   if (!flags.testing) {
     // Tests are not running. Reject the promise after given timeout.
     onAbort = DevToolsUtils.waitForTime(timeout).then(() => {
-      return promise.reject("Image '" + image.src + "' took too long to load.");
+      return Promise.reject("Image '" + image.src + "' took too long to load.");
     });
   }
 
   // See which happens first.
-  return promise.race([onLoad, onError, onAbort]);
+  return Promise.race([onLoad, onError, onAbort]);
 }
 
 /**
  * Given an <img> or <canvas> element, return the image data-uri. If @param node
  * is an <img> element, the method waits a while for the image to load before
  * the data is generated. If the image does not finish loading in a reasonable
  * time (IMAGE_FETCHING_TIMEOUT milliseconds) the process aborts.
  *
--- a/devtools/server/actors/source.js
+++ b/devtools/server/actors/source.js
@@ -10,17 +10,16 @@ const { Cc, Ci } = require("chrome");
 const Services = require("Services");
 const { BreakpointActor, setBreakpointAtEntryPoints } = require("devtools/server/actors/breakpoint");
 const { OriginalLocation, GeneratedLocation } = require("devtools/server/actors/common");
 const { createValueGrip, arrayBufferGrip } = require("devtools/server/actors/object");
 const { ActorClassWithSpec } = require("devtools/shared/protocol");
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 const { assert, fetch } = DevToolsUtils;
 const { joinURI } = require("devtools/shared/path");
-const promise = require("promise");
 const { sourceSpec } = require("devtools/shared/specs/source");
 
 loader.lazyRequireGetter(this, "SourceMapConsumer", "source-map", true);
 loader.lazyRequireGetter(this, "SourceMapGenerator", "source-map", true);
 loader.lazyRequireGetter(this, "mapURIToAddonID", "devtools/server/actors/utils/map-uri-to-addon-id");
 
 function isEvalSource(source) {
   let introType = source.introductionType;
@@ -474,17 +473,17 @@ let SourceActor = ActorClassWithSpec(sou
 
     return offsets;
   },
 
   /**
    * Handler for the "source" packet.
    */
   onSource: function () {
-    return promise.resolve(this._init)
+    return Promise.resolve(this._init)
       .then(this._getSourceText)
       .then(({ content, contentType }) => {
         if (typeof content === "object" && content && content.constructor &&
             content.constructor.name === "ArrayBuffer") {
           return {
             source: arrayBufferGrip(content, this.threadActor.threadLifetimePool),
             contentType,
           };
@@ -783,17 +782,17 @@ let SourceActor = ActorClassWithSpec(sou
         // to how scripts are kept alive. A parent Debugger.Script
         // keeps all of its children alive, so as long as we have a
         // valid script, we can slide through it and know we won't
         // slide through any of its child scripts. Additionally, if a
         // script gets GCed, that means that all parents scripts are
         // GCed as well, and no scripts will exist on those lines
         // anymore. We will never slide through a GCed script.
         if (originalLocation.originalColumn || scripts.length === 0) {
-          return promise.resolve(actor);
+          return Promise.resolve(actor);
         }
 
         // Find the script that spans the largest amount of code to
         // determine the bounds for sliding.
         const largestScript = scripts.reduce((largestScr, script) => {
           if (script.lineCount > largestScr.lineCount) {
             return script;
           }
@@ -809,17 +808,17 @@ let SourceActor = ActorClassWithSpec(sou
           }
         }
 
         // The above loop should never complete. We only did breakpoint sliding
         // because we found scripts on the line we started from,
         // which means there must be valid entry points somewhere
         // within those scripts.
         if (actualLine > maxLine) {
-          return promise.reject({
+          return Promise.reject({
             error: "noCodeAtLineColumn",
             message:
               "Could not find any entry points to set a breakpoint on, " +
               "even though I was told a script existed on the line I started " +
               "the search with."
           });
         }
 
@@ -832,17 +831,17 @@ let SourceActor = ActorClassWithSpec(sou
           actor.delete();
           actor = existingActor;
         } else {
           actor.originalLocation = actualLocation;
           this.breakpointActorMap.setActor(actualLocation, actor);
         }
       }
 
-      return promise.resolve(actor);
+      return Promise.resolve(actor);
     }
     return this.sources.getAllGeneratedLocations(originalLocation)
       .then((generatedLocations) => {
         this._setBreakpointAtAllGeneratedLocations(
           actor,
           generatedLocations
         );
 
--- a/devtools/server/actors/storage.js
+++ b/devtools/server/actors/storage.js
@@ -4,17 +4,16 @@
 
 "use strict";
 
 const {Cc, Ci, Cu, CC} = require("chrome");
 const protocol = require("devtools/shared/protocol");
 const {LongStringActor} = require("devtools/server/actors/string");
 const {DebuggerServer} = require("devtools/server/main");
 const Services = require("Services");
-const promise = require("promise");
 const defer = require("devtools/shared/defer");
 const {isWindowIncluded} = require("devtools/shared/layout/utils");
 const specs = require("devtools/shared/specs/storage");
 const { Task } = require("devtools/shared/task");
 
 const DEFAULT_VALUE = "value";
 
 loader.lazyRequireGetter(this, "naturalSortCaseInsensitive",
@@ -1449,17 +1448,17 @@ StorageActors.createActor({
     const parsedName = JSON.parse(name);
 
     // Only a Cache object is a valid object to clear
     if (parsedName.length == 1) {
       const [ cacheName ] = parsedName;
       const cache = cacheMap.get(cacheName);
       if (cache) {
         let keys = yield cache.keys();
-        yield promise.all(keys.map(key => cache.delete(key)));
+        yield Promise.all(keys.map(key => cache.delete(key)));
         this.onItemUpdated("cleared", host, [ cacheName ]);
       }
     }
   }),
 
   /**
    * CacheStorage API doesn't support any notifications, we must fake them
    */
--- a/devtools/server/actors/string.js
+++ b/devtools/server/actors/string.js
@@ -1,18 +1,16 @@
 /* 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 {DebuggerServer} = require("devtools/server/main");
 
-var promise = require("promise");
-
 var protocol = require("devtools/shared/protocol");
 const {longStringSpec} = require("devtools/shared/specs/string");
 
 exports.LongStringActor = protocol.ActorClassWithSpec(longStringSpec, {
   initialize: function (conn, str) {
     protocol.Actor.prototype.initialize.call(this, conn);
     this.str = str;
     this.short = (this.str.length < DebuggerServer.LONG_STRING_LENGTH);
@@ -31,13 +29,13 @@ exports.LongStringActor = protocol.Actor
       type: "longString",
       actor: this.actorID,
       length: this.str.length,
       initial: this.str.substring(0, DebuggerServer.LONG_STRING_INITIAL_LENGTH)
     };
   },
 
   substring: function (start, end) {
-    return promise.resolve(this.str.substring(start, end));
+    return Promise.resolve(this.str.substring(start, end));
   },
 
   release: function () { }
 });
--- a/devtools/server/actors/styles.js
+++ b/devtools/server/actors/styles.js
@@ -1,16 +1,15 @@
 /* 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";
 
 const {Ci} = require("chrome");
-const promise = require("promise");
 const protocol = require("devtools/shared/protocol");
 const {LongStringActor} = require("devtools/server/actors/string");
 const {Task} = require("devtools/shared/task");
 const InspectorUtils = require("InspectorUtils");
 
 // This will also add the "stylesheet" actor type for protocol.js to recognize
 
 const {pageStyleSpec, styleRuleSpec, ELEMENT_STYLE} = require("devtools/shared/specs/styles");
@@ -1232,21 +1231,21 @@ var StyleRuleActor = protocol.ActorClass
    * authored form is available, this also sets |this.authoredText|.
    * The authored text will include invalid and otherwise ignored
    * properties.
    */
   getAuthoredCssText: function () {
     if (!this.canSetRuleText ||
         (this.type !== CSSRule.STYLE_RULE &&
          this.type !== CSSRule.KEYFRAME_RULE)) {
-      return promise.resolve("");
+      return Promise.resolve("");
     }
 
     if (typeof this.authoredText === "string") {
-      return promise.resolve(this.authoredText);
+      return Promise.resolve(this.authoredText);
     }
 
     let parentStyleSheet =
         this.pageStyle._sheetRef(this._parentSheet);
     return parentStyleSheet.getText().then((longStr) => {
       let cssText = longStr.str;
       let {text} = getRuleText(cssText, this.line, this.column);
 
--- a/devtools/server/actors/stylesheets.js
+++ b/devtools/server/actors/stylesheets.js
@@ -1,17 +1,16 @@
 /* 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";
 
 const {Ci} = require("chrome");
 const Services = require("Services");
-const promise = require("promise");
 const defer = require("devtools/shared/defer");
 const {Task} = require("devtools/shared/task");
 const protocol = require("devtools/shared/protocol");
 const {LongStringActor} = require("devtools/server/actors/string");
 const {fetch} = require("devtools/shared/DevToolsUtils");
 const {mediaRuleSpec, styleSheetSpec,
        styleSheetsSpec} = require("devtools/shared/specs/stylesheets");
 const {
@@ -254,21 +253,21 @@ var StyleSheetActor = protocol.ActorClas
     let rules;
     try {
       rules = this.rawSheet.cssRules;
     } catch (e) {
       // sheet isn't loaded yet
     }
 
     if (rules) {
-      return promise.resolve(rules);
+      return Promise.resolve(rules);
     }
 
     if (!this.ownerNode) {
-      return promise.resolve([]);
+      return Promise.resolve([]);
     }
 
     if (this._cssRules) {
       return this._cssRules;
     }
 
     let deferred = defer();
 
@@ -366,30 +365,30 @@ var StyleSheetActor = protocol.ActorClas
    * Fetch the text for this stylesheet from the cache or network. Return
    * cached text if it's already been fetched.
    *
    * @return {Promise}
    *         Promise that resolves with a string text of the stylesheet.
    */
   _getText: function () {
     if (typeof this.text === "string") {
-      return promise.resolve(this.text);
+      return Promise.resolve(this.text);
     }
 
     let cssText = modifiedStyleSheets.get(this.rawSheet);
     if (cssText !== undefined) {
       this.text = cssText;
-      return promise.resolve(cssText);
+      return Promise.resolve(cssText);
     }
 
     if (!this.href) {
       // this is an inline <style> sheet
       let content = this.ownerNode.textContent;
       this.text = content;
-      return promise.resolve(content);
+      return Promise.resolve(content);
     }
 
     return this.fetchStylesheet(this.href).then(({ content }) => {
       this.text = content;
       return content;
     });
   },
 
--- a/devtools/server/actors/thread.js
+++ b/devtools/server/actors/thread.js
@@ -9,22 +9,19 @@
 const Services = require("Services");
 const { Cc, Ci, Cr } = require("chrome");
 const { ActorPool, GeneratedLocation } = require("devtools/server/actors/common");
 const { createValueGrip, longStringGrip } = require("devtools/server/actors/object");
 const { ActorClassWithSpec } = require("devtools/shared/protocol");
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 const flags = require("devtools/shared/flags");
 const { assert, dumpn } = DevToolsUtils;
-const promise = require("promise");
 const { DevToolsWorker } = require("devtools/shared/worker/worker");
 const { threadSpec } = require("devtools/shared/specs/script");
 
-const { resolve, reject, all } = promise;
-
 loader.lazyGetter(this, "Debugger", () => {
   let Debugger = require("Debugger");
   hackDebugger(Debugger);
   return Debugger;
 });
 loader.lazyRequireGetter(this, "findCssSelector", "devtools/shared/inspector/css-logic", true);
 loader.lazyRequireGetter(this, "BreakpointActor", "devtools/server/actors/breakpoint", true);
 loader.lazyRequireGetter(this, "setBreakpointAtEntryPoints", "devtools/server/actors/breakpoint", true);
@@ -375,17 +372,17 @@ const ThreadActor = ActorClassWithSpec(t
                       return undefined;
                     }
 
                     packet.frame.where = {
                       source: originalLocation.originalSourceActor.form(),
                       line: originalLocation.originalLine,
                       column: originalLocation.originalColumn
                     };
-                    resolve(onPacket(packet))
+                    Promise.resolve(onPacket(packet))
           .catch(error => {
             reportError(error);
             return {
               error: "unknownError",
               message: error.message + "\n" + error.stack
             };
           })
           .then(pkt => {
@@ -560,18 +557,18 @@ const ThreadActor = ActorClassWithSpec(t
    * @param Object request
    *        The request packet received over the RDP.
    * @returns A promise that resolves to true once the hooks are attached, or is
    *          rejected with an error packet.
    */
   _handleResumeLimit: function (request) {
     let steppingType = request.resumeLimit.type;
     if (!["break", "step", "next", "finish"].includes(steppingType)) {
-      return reject({ error: "badParameterType",
-                      message: "Unknown resumeLimit type" });
+      return Promise.reject({ error: "badParameterType",
+                              message: "Unknown resumeLimit type" });
     }
 
     const generatedLocation = this.sources.getFrameLocation(this.youngestFrame);
     return this.sources.getOriginalLocation(generatedLocation)
       .then(originalLocation => {
         const { onEnterFrame, onPop, onStep } = this._makeSteppingHooks(originalLocation,
                                                                         steppingType);
 
@@ -671,17 +668,17 @@ const ThreadActor = ActorClassWithSpec(t
       };
     }
 
     let resumeLimitHandled;
     if (request && request.resumeLimit) {
       resumeLimitHandled = this._handleResumeLimit(request);
     } else {
       this._clearSteppingHooks(this.youngestFrame);
-      resumeLimitHandled = resolve(true);
+      resumeLimitHandled = Promise.resolve(true);
     }
 
     return resumeLimitHandled.then(() => {
       if (request) {
         this._options.pauseOnExceptions = request.pauseOnExceptions;
         this._options.ignoreCaughtExceptions = request.ignoreCaughtExceptions;
         this.maybePauseOnExceptions();
         this._maybeListenToEvents(request);
@@ -942,17 +939,17 @@ const ThreadActor = ActorClassWithSpec(t
           column: originalLocation.originalColumn
         };
         form.source = sourceForm;
         return form;
       });
       promises.push(framePromise);
     }
 
-    return all(promises).then(function (frames) {
+    return Promise.all(promises).then(function (frames) {
       // Filter null values because sourcemapping may have failed.
       return { frames: frames.filter(x => !!x) };
     });
   },
 
   onReleaseMany: function (request) {
     if (!request.actors) {
       return { error: "missingParameter",
@@ -984,17 +981,17 @@ const ThreadActor = ActorClassWithSpec(t
 
     for (let i = 0, len = scripts.length; i < len; i++) {
       let s = scripts[i];
       if (s.source) {
         sourcesToScripts.set(s.source, s);
       }
     }
 
-    return all([...sourcesToScripts.values()].map(script => {
+    return Promise.all([...sourcesToScripts.values()].map(script => {
       return this.sources.createSourceActors(script.source);
     }));
   },
 
   onSources: function (request) {
     return this._discoverSources().then(() => {
       // No need to flush the new source packets here, as we are sending the
       // list of sources out immediately and we don't need to invoke the
@@ -1639,17 +1636,17 @@ const ThreadActor = ActorClassWithSpec(t
                   sourceActor._setBreakpointAtAllGeneratedLocations(
                     actor, generatedLocations);
                 }
               }));
         }
       }
 
       if (promises.length > 0) {
-        this.unsafeSynchronize(promise.all(promises));
+        this.unsafeSynchronize(Promise.all(promises));
       }
     } else {
       // Bug 1225160: If addSource is called in response to a new script
       // notification, and this notification was triggered by loading a JSM from
       // chrome code, calling unsafeSynchronize could cause a debuggee timer to
       // fire. If this causes the JSM to be loaded a second time, the browser
       // will crash, because loading JSMS is not reentrant, and the first load
       // has not completed yet.
--- a/devtools/server/actors/utils/TabSources.js
+++ b/devtools/server/actors/utils/TabSources.js
@@ -3,17 +3,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 const { assert, fetch } = DevToolsUtils;
 const EventEmitter = require("devtools/shared/old-event-emitter");
 const { OriginalLocation, GeneratedLocation } = require("devtools/server/actors/common");
-const { resolve } = require("promise");
 const { joinURI } = require("devtools/shared/path");
 
 loader.lazyRequireGetter(this, "SourceActor", "devtools/server/actors/source", true);
 loader.lazyRequireGetter(this, "isEvalSource", "devtools/server/actors/source", true);
 loader.lazyRequireGetter(this, "SourceMapConsumer", "source-map", true);
 loader.lazyRequireGetter(this, "SourceMapGenerator", "source-map", true);
 loader.lazyRequireGetter(this, "WasmRemap", "devtools/shared/wasm-source-map", true);
 
@@ -367,17 +366,17 @@ TabSources.prototype = {
    * instead of this.
    *
    * @param Debugger.Source source
    *        The source instance to create actors for.
    * @return Promise of an array of source actors
    */
   _createSourceMappedActors: function (source) {
     if (!this._useSourceMaps || !source.sourceMapURL) {
-      return resolve(null);
+      return Promise.resolve(null);
     }
 
     return this.fetchSourceMap(source)
       .then(map => {
         if (map) {
           return map.sources.map(s => {
             return this.source({ originalUrl: s, generatedSource: source });
           }).filter(isNotNull);
@@ -410,21 +409,21 @@ TabSources.prototype = {
    * and source maps are enabled (see `_fetchSourceMap`).
    *
    * @param Debugger.Source source
    *        The source instance to get sourcemaps for.
    * @return Promise of a SourceMapConsumer
    */
   fetchSourceMap: function (source) {
     if (!this._useSourceMaps) {
-      return resolve(null);
+      return Promise.resolve(null);
     } else if (this._sourceMaps.has(source)) {
       return this._sourceMaps.get(source);
     } else if (!source || !source.sourceMapURL) {
-      return resolve(null);
+      return Promise.resolve(null);
     }
 
     let sourceMapURL = source.sourceMapURL;
     if (source.url) {
       sourceMapURL = joinURI(source.url, sourceMapURL);
     }
     let result = this._fetchSourceMap(sourceMapURL, source.url);
 
@@ -441,24 +440,24 @@ TabSources.prototype = {
   },
 
   /**
    * Return a promise of a SourceMapConsumer for the source map for
    * `source`. The resolved result may be null if the source does not
    * have a source map or source maps are disabled.
    */
   getSourceMap: function (source) {
-    return resolve(this._sourceMaps.get(source));
+    return Promise.resolve(this._sourceMaps.get(source));
   },
 
   /**
    * Set a SourceMapConsumer for the source map for |source|.
    */
   setSourceMap: function (source, map) {
-    this._sourceMaps.set(source, resolve(map));
+    this._sourceMaps.set(source, Promise.resolve(map));
   },
 
   /**
    * Return a promise of a SourceMapConsumer for the source map located at
    * |absSourceMapURL|, which must be absolute. If there is already such a
    * promise extant, return it. This will not fetch if source maps are
    * disabled.
    *
@@ -561,17 +560,17 @@ TabSources.prototype = {
       // avoid tons of work serializing the sourcemap into a data url,
       // just make a fake URL and stick the sourcemap there.
       url = "internal://sourcemap" + (this._anonSourceMapId++) + "/";
     }
     source.sourceMapURL = url;
 
     // Forcefully set the sourcemap cache. This will be used even if
     // sourcemaps are disabled.
-    this._sourceMapCache[url] = resolve(map);
+    this._sourceMapCache[url] = Promise.resolve(map);
     this.emit("updatedSource", this.getSourceActor(source));
   },
 
   /**
    * Return the non-source-mapped location of the given Debugger.Frame. If the
    * frame does not have a script, the location's properties are all null.
    *
    * @param Debugger.Frame frame
--- a/devtools/server/actors/webbrowser.js
+++ b/devtools/server/actors/webbrowser.js
@@ -3,17 +3,16 @@
 /* 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 { Ci } = require("chrome");
 var Services = require("Services");
-var promise = require("promise");
 const defer = require("devtools/shared/defer");
 var { DebuggerServer } = require("devtools/server/main");
 var DevToolsUtils = require("devtools/shared/DevToolsUtils");
 
 loader.lazyRequireGetter(this, "RootActor", "devtools/server/actors/root", true);
 loader.lazyRequireGetter(this, "BrowserAddonActor", "devtools/server/actors/addon", true);
 loader.lazyRequireGetter(this, "WebExtensionParentActor", "devtools/server/actors/webextension-parent", true);
 loader.lazyRequireGetter(this, "WorkerActorList", "devtools/server/actors/worker-list", true);
@@ -299,17 +298,17 @@ BrowserTabList.prototype.getList = funct
 
   if (this._testing && initialMapSize !== this._foundCount) {
     throw new Error("_actorByBrowser map contained actors for dead tabs");
   }
 
   this._mustNotify = true;
   this._checkListening();
 
-  return promise.all(actorPromises).then(values => {
+  return Promise.all(actorPromises).then(values => {
     // Filter out null values if we received a tabDestroyed error.
     return values.filter(value => value != null);
   });
 };
 
 /**
  * @param browserActorOptions see options argument of BrowserTabActor constructor.
  */
@@ -328,17 +327,17 @@ BrowserTabList.prototype._getActorForBro
 };
 
 BrowserTabList.prototype.getTab = function ({ outerWindowID, tabId }) {
   if (typeof outerWindowID == "number") {
     // First look for in-process frames with this ID
     let window = Services.wm.getOuterWindowWithId(outerWindowID);
     // Safety check to prevent debugging top level window via getTab
     if (window && window.isChromeWindow) {
-      return promise.reject({
+      return Promise.reject({
         error: "forbidden",
         message: "Window with outerWindowID '" + outerWindowID + "' is chrome"
       });
     }
     if (window) {
       let iframe = window.QueryInterface(Ci.nsIInterfaceRequestor)
                          .getInterface(Ci.nsIDOMWindowUtils)
                          .containerElement;
@@ -348,42 +347,42 @@ BrowserTabList.prototype.getTab = functi
     }
     // Then also look on registered <xul:browsers> when using outerWindowID for
     // OOP tabs
     for (let browser of this._getBrowsers()) {
       if (browser.outerWindowID == outerWindowID) {
         return this._getActorForBrowser(browser);
       }
     }
-    return promise.reject({
+    return Promise.reject({
       error: "noTab",
       message: "Unable to find tab with outerWindowID '" + outerWindowID + "'"
     });
   } else if (typeof tabId == "number") {
     // Tabs OOP
     for (let browser of this._getBrowsers()) {
       if (browser.frameLoader &&
           browser.frameLoader.tabParent &&
           browser.frameLoader.tabParent.tabId === tabId) {
         return this._getActorForBrowser(browser);
       }
     }
-    return promise.reject({
+    return Promise.reject({
       error: "noTab",
       message: "Unable to find tab with tabId '" + tabId + "'"
     });
   }
 
   let topXULWindow = Services.wm.getMostRecentWindow(
     DebuggerServer.chromeWindowType);
   if (topXULWindow) {
     let selectedBrowser = this._getSelectedBrowser(topXULWindow);
     return this._getActorForBrowser(selectedBrowser);
   }
-  return promise.reject({
+  return Promise.reject({
     error: "noTab",
     message: "Unable to find any selected browser"
   });
 };
 
 Object.defineProperty(BrowserTabList.prototype, "onListChanged", {
   enumerable: true,
   configurable: true,
--- a/devtools/server/performance/recorder.js
+++ b/devtools/server/performance/recorder.js
@@ -2,17 +2,16 @@
  * 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";
 
 const { Cu } = require("chrome");
 const { Task } = require("devtools/shared/task");
 
 loader.lazyRequireGetter(this, "Services");
-loader.lazyRequireGetter(this, "promise");
 loader.lazyRequireGetter(this, "EventEmitter", "devtools/shared/event-emitter");
 
 loader.lazyRequireGetter(this, "Memory",
   "devtools/server/performance/memory", true);
 loader.lazyRequireGetter(this, "Timeline",
   "devtools/server/performance/timeline", true);
 loader.lazyRequireGetter(this, "Profiler",
   "devtools/server/performance/profiler", true);
@@ -343,17 +342,17 @@ PerformanceRecorder.prototype = {
         this._memory.attach();
       }
       let recordingOptions = Object.assign(mapRecordingOptions("memory", options), {
         drainAllocationsTimeout: DRAIN_ALLOCATIONS_TIMEOUT
       });
       memoryStart = this._memory.startRecordingAllocations(recordingOptions);
     }
 
-    let [profilerStartData, timelineStartData, memoryStartData] = yield promise.all([
+    let [profilerStartData, timelineStartData, memoryStartData] = yield Promise.all([
       profilerStart, timelineStart, memoryStart
     ]);
 
     let data = Object.create(null);
     // Filter out start times that are not actually used (0 or undefined), and
     // find the earliest time since all sources use same epoch.
     let startTimes = [
       profilerStartData.currentTime,
--- a/devtools/server/tests/mochitest/inspector-helpers.js
+++ b/devtools/server/tests/mochitest/inspector-helpers.js
@@ -6,17 +6,16 @@
 
 const {require} = ChromeUtils.import("resource://devtools/shared/Loader.jsm", {});
 const {DebuggerClient} = require("devtools/shared/client/debugger-client");
 const {DebuggerServer} = require("devtools/server/main");
 const { Task } = require("devtools/shared/task");
 
 const Services = require("Services");
 // promise is still used in tests using this helper
-const promise = require("promise"); // eslint-disable-line no-unused-vars
 const defer = require("devtools/shared/defer");
 const {DocumentWalker: _documentWalker} = require("devtools/server/actors/inspector/document-walker");
 
 // Always log packets when running tests.
 Services.prefs.setBoolPref("devtools.debugger.log", true);
 SimpleTest.registerCleanupFunction(function () {
   Services.prefs.clearUserPref("devtools.debugger.log");
 });
--- a/devtools/server/tests/mochitest/test_inspector-mutations-childlist.html
+++ b/devtools/server/tests/mochitest/test_inspector-mutations-childlist.html
@@ -59,17 +59,17 @@ function setParent(nodeSelector, newPare
 
 function loadSelector(selector) {
   return gWalker.querySelectorAll(gWalker.rootNode, selector).then(nodeList => {
     return nodeList.items();
   });
 }
 
 function loadSelectors(selectors) {
-  return promise.all(Array.from(selectors, (sel) => loadSelector(sel)));
+  return Promise.all(Array.from(selectors, (sel) => loadSelector(sel)));
 }
 
 function doMoves(moves) {
   for (let move of moves) {
     setParent(move[0], move[1]);
   }
 }
 
--- a/devtools/server/tests/mochitest/test_inspector-resize.html
+++ b/devtools/server/tests/mochitest/test_inspector-resize.html
@@ -10,31 +10,30 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
   <script type="application/javascript" src="inspector-helpers.js"></script>
   <script type="application/javascript">
 "use strict";
 
 window.onload = function () {
   const {require} = ChromeUtils.import("resource://devtools/shared/Loader.jsm", {});
-  const promise = require("promise");
   const {InspectorFront} = require("devtools/shared/fronts/inspector");
 
   SimpleTest.waitForExplicitFinish();
 
   let win = null;
   let inspector = null;
 
   addAsyncTest(function* setup() {
     info("Setting up inspector and walker actors.");
 
     let url = document.getElementById("inspectorContent").href;
 
     // eslint-disable-next-line new-cap
-    yield new promise(resolve => {
+    yield new Promise(resolve => {
       attachURL(url, function (err, client, tab, doc) {
         win = doc.defaultView;
         inspector = InspectorFront(client, tab);
         resolve();
       });
     });
 
     runNextTest();
@@ -44,17 +43,17 @@ window.onload = function () {
     let walker = yield inspector.getWalker();
 
     // We can't receive events from the walker if we haven't first executed a
     // method on the actor to initialize it.
     yield walker.querySelector(walker.rootNode, "img");
 
     let {outerWidth, outerHeight} = win;
     // eslint-disable-next-line new-cap
-    let onResize = new promise(resolve => {
+    let onResize = new Promise(resolve => {
       walker.once("resize", () => {
         resolve();
       });
     });
     win.resizeTo(800, 600);
     yield onResize;
 
     ok(true, "The resize event was emitted");
--- a/devtools/server/tests/mochitest/test_inspector-retain.html
+++ b/devtools/server/tests/mochitest/test_inspector-retain.html
@@ -106,17 +106,17 @@ addTest(function testRetain() {
 // retain request), because we haven't issued `getMutations` yet.
 addTest(function testWinRace() {
   let front = null;
   promiseDone(gWalker.querySelector(gWalker.rootNode, "#a").then(node => {
     front = node;
     let contentNode = gInspectee.querySelector("#a");
     contentNode.remove();
     // Now wait for that mutation and retain response to come in.
-    return promise.all([
+    return Promise.all([
       gWalker.retainNode(front),
       waitForMutation(gWalker, isChildList)
     ]);
   }).then(() => {
     assertOwnership();
     is(gWalker._retainedOrphans.size, 1, "Should have a retained orphan.");
     ok(gWalker._retainedOrphans.has(front), "Should have retained our expected node.");
     return gWalker.unretainNode(front);
--- a/devtools/server/tests/mochitest/test_inspector-search-front.html
+++ b/devtools/server/tests/mochitest/test_inspector-search-front.html
@@ -9,17 +9,16 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
   <script type="application/javascript" src="inspector-helpers.js"></script>
   <script type="application/javascript">
 "use strict";
 
 window.onload = function () {
   const {require} = ChromeUtils.import("resource://devtools/shared/Loader.jsm", {});
-  const promise = require("promise");
   const {InspectorFront} = require("devtools/shared/fronts/inspector");
 
   SimpleTest.waitForExplicitFinish();
 
   let walkerFront = null;
   let inspector = null;
 
   // WalkerFront specific tests.  These aren't to excercise search
@@ -28,17 +27,17 @@ window.onload = function () {
   // See also test_inspector-search.html
 
   addAsyncTest(function* setup() {
     info("Setting up inspector and walker actors.");
 
     let url = document.getElementById("inspectorContent").href;
 
     // eslint-disable-next-line new-cap
-    yield new promise(resolve => {
+    yield new Promise(resolve => {
       attachURL(url, function (err, client, tab, doc) {
         inspector = InspectorFront(client, tab);
         resolve();
       });
     });
 
     walkerFront = yield inspector.getWalker();
     ok(walkerFront, "getWalker() should return an actor.");
--- a/devtools/server/tests/mochitest/test_inspector-search.html
+++ b/devtools/server/tests/mochitest/test_inspector-search.html
@@ -9,17 +9,16 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
   <script type="application/javascript" src="inspector-helpers.js"></script>
   <script type="application/javascript">
 "use strict";
 
 window.onload = function () {
   const {require} = ChromeUtils.import("resource://devtools/shared/Loader.jsm", {});
-  const promise = require("promise");
   const {InspectorFront} = require("devtools/shared/fronts/inspector");
   const {WalkerSearch, WalkerIndex} =
     require("devtools/server/actors/utils/walker-search");
 
   SimpleTest.waitForExplicitFinish();
 
   let walkerActor = null;
   let walkerSearch = null;
@@ -31,17 +30,17 @@ window.onload = function () {
   // See also test_inspector-search-front.html.
 
   addAsyncTest(function* setup() {
     info("Setting up inspector and walker actors.");
 
     let url = document.getElementById("inspectorContent").href;
 
     // eslint-disable-next-line new-cap
-    yield new promise(resolve => {
+    yield new Promise(resolve => {
       attachURL(url, function (err, client, tab, doc) {
         inspectee = doc;
         inspector = InspectorFront(client, tab);
         resolve();
       });
     });
 
     let walkerFront = yield inspector.getWalker();
@@ -235,34 +234,34 @@ window.onload = function () {
 
     results = walkerSearch.search("h3");
     isDeeply(results, [
       expected[1],
       expected[2]
     ], "Results are updated after removal");
 
     // eslint-disable-next-line new-cap
-    yield new promise(resolve => {
+    yield new Promise(resolve => {
       info("Waiting for a mutation to happen");
       let observer = new inspectee.defaultView.MutationObserver(() => {
         resolve();
       });
       observer.observe(inspectee, {attributes: true, subtree: true});
       inspectee.body.setAttribute("h3", "true");
     });
 
     results = walkerSearch.search("h3");
     isDeeply(results, [
       {node: inspectee.body, type: "attributeName"},
       expected[1],
       expected[2]
     ], "Results are updated after addition");
 
     // eslint-disable-next-line new-cap
-    yield new promise(resolve => {
+    yield new Promise(resolve => {
       info("Waiting for a mutation to happen");
       let observer = new inspectee.defaultView.MutationObserver(() => {
         resolve();
       });
       observer.observe(inspectee, {attributes: true, childList: true, subtree: true});
       inspectee.body.removeAttribute("h3");
       expected[1].node.remove();
       expected[2].node.remove();
@@ -273,17 +272,17 @@ window.onload = function () {
 
     runNextTest();
   });
 
   runNextTest();
 
   function mutateDocumentAndWaitForMutation(mutationFn) {
     // eslint-disable-next-line new-cap
-    return new promise(resolve => {
+    return new Promise(resolve => {
       info("Listening to markup mutation on the inspectee");
       let observer = new inspectee.defaultView.MutationObserver(resolve);
       observer.observe(inspectee, {childList: true, subtree: true});
       mutationFn();
     });
   }
 };
   </script>
--- a/devtools/server/tests/mochitest/test_inspector-traversal.html
+++ b/devtools/server/tests/mochitest/test_inspector-traversal.html
@@ -332,17 +332,17 @@ addTest(function testShortValue() {
   }).then(runNextTest));
 });
 
 addTest(function testReleaseWalker() {
   checkActorIDs.push(gWalker.actorID);
 
   promiseDone(gWalker.release().then(() => {
     let promises = Array.from(checkActorIDs, (id) => checkMissing(gClient, id));
-    return promise.all(promises);
+    return Promise.all(promises);
   }).then(runNextTest));
 });
 
 addTest(function cleanup() {
   gWalker = null;
   gInspectee = null;
   gClient = null;
   runNextTest();
--- a/devtools/server/tests/unit/head_dbg.js
+++ b/devtools/server/tests/unit/head_dbg.js
@@ -15,17 +15,16 @@ ChromeUtils.import("resource://testing-c
   name: "devtools-tests",
   version: "1",
   platformVersion: "42",
   crashReporter: true,
 });
 
 const { require, loader } = ChromeUtils.import("resource://devtools/shared/Loader.jsm", {});
 const { worker } = ChromeUtils.import("resource://devtools/shared/worker/loader.js", {});
-const promise = require("promise");
 const defer = require("devtools/shared/defer");
 const { Task } = require("devtools/shared/task");
 const { console } = require("resource://gre/modules/Console.jsm");
 const { NetUtil } = require("resource://gre/modules/NetUtil.jsm");
 
 const Services = require("Services");
 // Always log packets when running tests. runxpcshelltests.py will throw
 // the output away anyway, unless you give it the --verbose flag.
--- a/devtools/server/tests/unit/test_blackboxing-06.js
+++ b/devtools/server/tests/unit/test_blackboxing-06.js
@@ -19,17 +19,17 @@ function run_test() {
   gDebuggee = addTestGlobal("test-black-box");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect().then(function () {
     attachTestTabAndResume(
       gClient, "test-black-box",
       function (response, tabClient, threadClient) {
         gThreadClient = threadClient;
 
-        promise.resolve(setup_code())
+        Promise.resolve(setup_code())
           .then(black_box_code)
           .then(run_code)
           .then(test_correct_location)
           .catch(function (error) {
             Assert.ok(false, "Should not get an error, got " + error);
           })
           .then(function () {
             finishClient(gClient);
--- a/devtools/server/tests/unit/test_protocol_async.js
+++ b/devtools/server/tests/unit/test_protocol_async.js
@@ -183,16 +183,16 @@ function run_test() {
       return deferAfterRejection.promise.then(function () {
         // Check right return order
         Assert.equal(sequence, 7);
         // Check request handling order
         Assert.equal(ret, sequence++);
       });
     }));
 
-    promise.all(calls).then(() => {
+    Promise.all(calls).then(() => {
       client.close().then(() => {
         do_test_finished();
       });
     });
   });
   do_test_pending();
 }
--- a/devtools/server/tests/unit/test_protocol_children.js
+++ b/devtools/server/tests/unit/test_protocol_children.js
@@ -187,17 +187,17 @@ var ChildFront = protocol.FrontClassWith
     this.detail = form.detail;
   },
 
   onEvent1: preEvent("event1", function (a, b, c) {
     this.event1arg3 = c;
   }),
 
   onEvent2a: preEvent("event2", function (a, b, c) {
-    return promise.resolve().then(() => {
+    return Promise.resolve().then(() => {
       this.event2arg3 = c;
     });
   }),
 
   onEvent2b: preEvent("event2", function (a, b, c) {
     this.event2arg2 = b;
   }),
 });
@@ -320,17 +320,17 @@ var RootFront = protocol.FrontClassWithS
     }
     return this._getTemporaryChild(id);
   }, {
     impl: "_getTemporaryChild"
   }),
 
   clearTemporaryChildren: protocol.custom(function () {
     if (!this._temporaryHolder) {
-      return promise.resolve(undefined);
+      return Promise.resolve(undefined);
     }
     this._temporaryHolder.destroy();
     delete this._temporaryHolder;
     return this._clearTemporaryChildren();
   }, {
     impl: "_clearTemporaryChildren"
   })
 });
--- a/devtools/server/tests/unit/test_protocol_simple.js
+++ b/devtools/server/tests/unit/test_protocol_simple.js
@@ -113,17 +113,17 @@ var RootActor = protocol.ActorClassWithS
 
   sayHello: simpleHello,
 
   simpleReturn: function () {
     return 1;
   },
 
   promiseReturn: function () {
-    return promise.resolve(1);
+    return Promise.resolve(1);
   },
 
   simpleArgs: function (a, b) {
     return { firstResponse: a + 1, secondResponse: b + 1 };
   },
 
   nestedArgs: function (a, b, c) {
     return { a: a, b: b, c: c };
--- a/devtools/server/tests/unit/test_sourcemaps-10.js
+++ b/devtools/server/tests/unit/test_sourcemaps-10.js
@@ -17,17 +17,17 @@ function run_test() {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-source-map");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect().then(function () {
     attachTestTabAndResume(
       gClient, "test-source-map",
       function (response, tabClient, threadClient) {
         gThreadClient = threadClient;
-        promise.resolve(define_code())
+        Promise.resolve(define_code())
           .then(run_code)
           .then(test_frame_location)
           .catch(error => {
             dump(error + "\n");
             dump(error.stack);
             Assert.ok(false);
           })
           .then(() => {
--- a/devtools/server/tests/unit/test_sourcemaps-11.js
+++ b/devtools/server/tests/unit/test_sourcemaps-11.js
@@ -17,17 +17,17 @@ function run_test() {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-source-map");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect().then(function () {
     attachTestTabAndResume(
       gClient, "test-source-map",
       function (response, tabClient, threadClient) {
         gThreadClient = threadClient;
-        promise.resolve(define_code())
+        Promise.resolve(define_code())
           .then(run_code)
           .then(test_frames)
           .catch(error => {
             dump(error + "\n");
             dump(error.stack);
             Assert.ok(false);
           })
           .then(() => {