Merge mozilla-inbound to mozilla-central. a=merge
authorDaniel Varga <dvarga@mozilla.com>
Wed, 20 Feb 2019 06:01:45 +0200
changeset 517896 bf3951daded0
parent 517854 62a8571d3b92 (current diff)
parent 517895 2a74c17e7363 (diff)
child 517901 72e2cb1f30b4
child 517974 eb4fd889c657
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone67.0a1
first release with
nightly linux32
bf3951daded0 / 67.0a1 / 20190220040540 / files
nightly linux64
bf3951daded0 / 67.0a1 / 20190220040540 / files
nightly mac
bf3951daded0 / 67.0a1 / 20190220040540 / files
nightly win32
bf3951daded0 / 67.0a1 / 20190220040540 / files
nightly win64
bf3951daded0 / 67.0a1 / 20190220040540 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-inbound to mozilla-central. a=merge
taskcluster/ci/build/linux.yml
taskcluster/ci/build/windows.yml
--- a/browser/config/mozconfigs/linux64/beta
+++ b/browser/config/mozconfigs/linux64/beta
@@ -1,8 +1,8 @@
-export MOZ_PGO=1
+. "$topsrcdir/build/mozconfig.pgo"
 
 . "$topsrcdir/browser/config/mozconfigs/linux64/common-opt"
 
 ac_add_options --enable-official-branding
 ac_add_options --enable-verify-mar
 
 . "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux64/release
+++ b/browser/config/mozconfigs/linux64/release
@@ -1,12 +1,12 @@
 # This make file should be identical to the beta mozconfig, apart from the
 # safeguard below
 
-export MOZ_PGO=1
+. "$topsrcdir/build/mozconfig.pgo"
 
 . "$topsrcdir/browser/config/mozconfigs/linux64/common-opt"
 
 ac_add_options --enable-official-branding
 ac_add_options --enable-verify-mar
 
 # safeguard against someone forgetting to re-set EARLY_BETA_OR_EARLIER in
 # defines.sh during the beta cycle
--- a/browser/config/mozconfigs/whitelist
+++ b/browser/config/mozconfigs/whitelist
@@ -37,14 +37,14 @@ whitelist['release']['win64'] += ['expor
 whitelist['release']['linux32'] += [
     'export MOZILLA_OFFICIAL=1',
     'export MOZ_TELEMETRY_REPORTING=1',
     'export MOZ_PGO=1',
 ]
 whitelist['release']['linux64'] += [
     'export MOZILLA_OFFICIAL=1',
     'export MOZ_TELEMETRY_REPORTING=1',
-    'export MOZ_PGO=1',
+    '. "$topsrcdir/build/mozconfig.pgo"',
 ]
 
 if __name__ == '__main__':
     import pprint
     pprint.pprint(whitelist)
--- a/browser/config/mozconfigs/win32/common-opt
+++ b/browser/config/mozconfigs/win32/common-opt
@@ -1,16 +1,15 @@
 # This file is sourced by the nightly, beta, and release mozconfigs.
 
 . "$topsrcdir/build/mozconfig.stylo"
 
 . "$topsrcdir/browser/config/mozconfigs/common"
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
-ac_add_options --enable-jemalloc
 
 if [ -f /c/builds/gapi.data ]; then
   _gapi_keyfile=c:/builds/gapi.data
 else
   _gapi_keyfile=e:/builds/gapi.data
 fi
 ac_add_options --with-google-api-keyfile=${_gapi_keyfile}
 
--- a/browser/config/mozconfigs/win64-aarch64/common-opt
+++ b/browser/config/mozconfigs/win64-aarch64/common-opt
@@ -1,16 +1,16 @@
 # This file is sourced by the nightly, beta, and release mozconfigs.
 
 . "$topsrcdir/build/mozconfig.stylo"
 
 . "$topsrcdir/browser/config/mozconfigs/common"
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
-ac_add_options --enable-jemalloc
+
 if [ -f /c/builds/gapi.data ]; then
   _gapi_keyfile=c:/builds/gapi.data
 else
   _gapi_keyfile=e:/builds/gapi.data
 fi
 ac_add_options --with-google-api-keyfile=${_gapi_keyfile}
 
 ac_add_options --with-mozilla-api-keyfile=c:/builds/mozilla-desktop-geoloc-api.key
--- a/browser/config/mozconfigs/win64/common-opt
+++ b/browser/config/mozconfigs/win64/common-opt
@@ -1,16 +1,16 @@
 # This file is sourced by the nightly, beta, and release mozconfigs.
 
 . "$topsrcdir/build/mozconfig.stylo"
 
 . "$topsrcdir/browser/config/mozconfigs/common"
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
-ac_add_options --enable-jemalloc
+
 if [ -f /c/builds/gapi.data ]; then
   _gapi_keyfile=c:/builds/gapi.data
 else
   _gapi_keyfile=e:/builds/gapi.data
 fi
 ac_add_options --with-google-api-keyfile=${_gapi_keyfile}
 
 ac_add_options --with-mozilla-api-keyfile=c:/builds/mozilla-desktop-geoloc-api.key
--- a/browser/extensions/pdfjs/README.mozilla
+++ b/browser/extensions/pdfjs/README.mozilla
@@ -1,5 +1,5 @@
 This is the PDF.js project output, https://github.com/mozilla/pdf.js
 
-Current extension version is: 2.1.266
+Current extension version is: 2.2.15
 
-Taken from upstream commit: 81f5835c
+Taken from upstream commit: ece6a31a
--- a/browser/extensions/pdfjs/content/PdfJsDefaultPreferences.jsm
+++ b/browser/extensions/pdfjs/content/PdfJsDefaultPreferences.jsm
@@ -17,30 +17,30 @@
 
 //
 // THIS FILE IS GENERATED AUTOMATICALLY, DO NOT EDIT MANUALLY!
 //
 
 "use strict";
 var EXPORTED_SYMBOLS = ["PdfJsDefaultPreferences"];
 var PdfJsDefaultPreferences = Object.freeze({
- "viewOnLoad": 0,
+ "cursorToolOnLoad": 0,
  "defaultZoomValue": "",
- "sidebarViewOnLoad": -1,
- "cursorToolOnLoad": 0,
+ "disablePageLabels": false,
+ "enablePrintAutoRotate": false,
  "enableWebGL": false,
  "eventBusDispatchToDOM": false,
+ "externalLinkTarget": 0,
+ "historyUpdateUrl": false,
  "pdfBugEnabled": false,
- "disableRange": false,
- "disableStream": false,
+ "renderer": "canvas",
+ "renderInteractiveForms": false,
+ "sidebarViewOnLoad": -1,
+ "scrollModeOnLoad": -1,
+ "spreadModeOnLoad": -1,
+ "textLayerMode": 1,
+ "useOnlyCssZoom": false,
+ "viewOnLoad": 0,
  "disableAutoFetch": false,
  "disableFontFace": false,
- "textLayerMode": 1,
- "useOnlyCssZoom": false,
- "externalLinkTarget": 0,
- "renderer": "canvas",
- "renderInteractiveForms": false,
- "enablePrintAutoRotate": false,
- "disablePageLabels": false,
- "historyUpdateUrl": false,
- "scrollModeOnLoad": -1,
- "spreadModeOnLoad": -1
+ "disableRange": false,
+ "disableStream": false
 });
--- a/browser/extensions/pdfjs/content/build/pdf.js
+++ b/browser/extensions/pdfjs/content/build/pdf.js
@@ -118,18 +118,18 @@ return /******/ (function(modules) { // 
 /************************************************************************/
 /******/ ([
 /* 0 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
 
-var pdfjsVersion = '2.1.266';
-var pdfjsBuild = '81f5835c';
+var pdfjsVersion = '2.2.15';
+var pdfjsBuild = 'ece6a31a';
 
 var pdfjsSharedUtil = __w_pdfjs_require__(1);
 
 var pdfjsDisplayAPI = __w_pdfjs_require__(6);
 
 var pdfjsDisplayTextLayer = __w_pdfjs_require__(18);
 
 var pdfjsDisplayAnnotationLayer = __w_pdfjs_require__(19);
@@ -1406,17 +1406,17 @@ function _fetchDocument(worker, source, 
 
   if (pdfDataRangeTransport) {
     source.length = pdfDataRangeTransport.length;
     source.initialData = pdfDataRangeTransport.initialData;
   }
 
   return worker.messageHandler.sendWithPromise('GetDocRequest', {
     docId,
-    apiVersion: '2.1.266',
+    apiVersion: '2.2.15',
     source: {
       data: source.data,
       url: source.url,
       password: source.password,
       disableAutoFetch: source.disableAutoFetch,
       rangeChunkSize: source.rangeChunkSize,
       length: source.length
     },
@@ -3143,19 +3143,19 @@ const InternalRenderTask = function Inte
       }
     }
 
   }
 
   return InternalRenderTask;
 }();
 
-const version = '2.1.266';
+const version = '2.2.15';
 exports.version = version;
-const build = '81f5835c';
+const build = 'ece6a31a';
 exports.build = build;
 
 /***/ }),
 /* 7 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
--- a/browser/extensions/pdfjs/content/build/pdf.worker.js
+++ b/browser/extensions/pdfjs/content/build/pdf.worker.js
@@ -118,18 +118,18 @@ return /******/ (function(modules) { // 
 /************************************************************************/
 /******/ ([
 /* 0 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
 
-const pdfjsVersion = '2.1.266';
-const pdfjsBuild = '81f5835c';
+const pdfjsVersion = '2.2.15';
+const pdfjsBuild = 'ece6a31a';
 
 const pdfjsCoreWorker = __w_pdfjs_require__(1);
 
 exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler;
 
 /***/ }),
 /* 1 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
@@ -370,17 +370,17 @@ var WorkerMessageHandler = {
   },
 
   createDocumentHandler(docParams, port) {
     var pdfManager;
     var terminated = false;
     var cancelXHRs = null;
     var WorkerTasks = [];
     let apiVersion = docParams.apiVersion;
-    let workerVersion = '2.1.266';
+    let workerVersion = '2.2.15';
 
     if (apiVersion !== workerVersion) {
       throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
     }
 
     var docId = docParams.docId;
     var docBaseUrl = docParams.docBaseUrl;
     var workerHandlerName = docParams.docId + '_worker';
@@ -3002,28 +3002,42 @@ class PDFDocument {
 
     try {
       this.acroForm = this.catalog.catDict.get('AcroForm');
 
       if (this.acroForm) {
         this.xfa = this.acroForm.get('XFA');
         const fields = this.acroForm.get('Fields');
 
-        if ((!fields || !Array.isArray(fields) || fields.length === 0) && !this.xfa) {
+        if ((!Array.isArray(fields) || fields.length === 0) && !this.xfa) {
           this.acroForm = null;
         }
       }
     } catch (ex) {
       if (ex instanceof _util.MissingDataException) {
         throw ex;
       }
 
       (0, _util.info)('Cannot fetch AcroForm entry; assuming no AcroForms are present');
       this.acroForm = null;
     }
+
+    try {
+      const collection = this.catalog.catDict.get('Collection');
+
+      if ((0, _primitives.isDict)(collection) && collection.getKeys().length > 0) {
+        this.collection = collection;
+      }
+    } catch (ex) {
+      if (ex instanceof _util.MissingDataException) {
+        throw ex;
+      }
+
+      (0, _util.info)('Cannot fetch Collection dictionary.');
+    }
   }
 
   get linearization() {
     let linearization = null;
 
     try {
       linearization = _parser.Linearization.create(this.stream);
     } catch (err) {
@@ -3142,17 +3156,18 @@ class PDFDocument {
       CreationDate: _util.isString,
       ModDate: _util.isString,
       Trapped: _primitives.isName
     };
     const docInfo = {
       PDFFormatVersion: this.pdfFormatVersion,
       IsLinearized: !!this.linearization,
       IsAcroFormPresent: !!this.acroForm,
-      IsXFAPresent: !!this.xfa
+      IsXFAPresent: !!this.xfa,
+      IsCollectionPresent: !!this.collection
     };
     let infoDict;
 
     try {
       infoDict = this.xref.trailer.get('Info');
     } catch (err) {
       if (err instanceof _util.MissingDataException) {
         throw err;
--- a/browser/extensions/pdfjs/content/web/viewer.js
+++ b/browser/extensions/pdfjs/content/web/viewer.js
@@ -112,17 +112,17 @@
 
 "use strict";
 
 
 ;
 let pdfjsWebApp, pdfjsWebAppOptions;
 {
   pdfjsWebApp = __webpack_require__(1);
-  pdfjsWebAppOptions = __webpack_require__(8);
+  pdfjsWebAppOptions = __webpack_require__(3);
 }
 {
   __webpack_require__(33);
 
   __webpack_require__(36);
 }
 ;
 ;
@@ -273,25 +273,25 @@ if (document.readyState === 'interactive
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.PDFPrintServiceFactory = exports.DefaultExternalServices = exports.PDFViewerApplication = void 0;
 
 var _ui_utils = __webpack_require__(2);
 
-var _pdfjsLib = __webpack_require__(3);
-
-var _pdf_cursor_tools = __webpack_require__(4);
-
-var _pdf_rendering_queue = __webpack_require__(6);
-
-var _pdf_sidebar = __webpack_require__(7);
-
-var _app_options = __webpack_require__(8);
+var _app_options = __webpack_require__(3);
+
+var _pdfjsLib = __webpack_require__(4);
+
+var _pdf_cursor_tools = __webpack_require__(6);
+
+var _pdf_rendering_queue = __webpack_require__(8);
+
+var _pdf_sidebar = __webpack_require__(9);
 
 var _overlay_manager = __webpack_require__(10);
 
 var _password_prompt = __webpack_require__(11);
 
 var _pdf_attachment_viewer = __webpack_require__(12);
 
 var _pdf_document_properties = __webpack_require__(13);
@@ -803,17 +803,17 @@ let PDFViewerApplication = {
     return promise;
   },
 
   async open(file, args) {
     if (this.pdfLoadingTask) {
       await this.close();
     }
 
-    const workerParameters = _app_options.AppOptions.getAll('worker');
+    const workerParameters = _app_options.AppOptions.getAll(_app_options.OptionKind.WORKER);
 
     for (let key in workerParameters) {
       _pdfjsLib.GlobalWorkerOptions[key] = workerParameters[key];
     }
 
     let parameters = Object.create(null);
 
     if (typeof file === 'string') {
@@ -823,17 +823,17 @@ let PDFViewerApplication = {
       parameters.data = file;
     } else if (file.url && file.originalUrl) {
       this.setTitleUsingUrl(file.originalUrl);
       parameters.url = file.url;
     }
 
     parameters.docBaseUrl = this.baseUrl;
 
-    const apiParameters = _app_options.AppOptions.getAll('api');
+    const apiParameters = _app_options.AppOptions.getAll(_app_options.OptionKind.API);
 
     for (let key in apiParameters) {
       parameters[key] = apiParameters[key];
     }
 
     if (args) {
       for (let prop in args) {
         if (prop === 'length') {
@@ -3098,39 +3098,281 @@ function moveToEndOfArray(arr, condition
 
 /***/ }),
 /* 3 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.OptionKind = exports.AppOptions = void 0;
+
+var _pdfjsLib = __webpack_require__(4);
+
+var _viewer_compatibility = __webpack_require__(5);
+
+const OptionKind = {
+  VIEWER: 0x02,
+  API: 0x04,
+  WORKER: 0x08,
+  PREFERENCE: 0x80
+};
+exports.OptionKind = OptionKind;
+const defaultOptions = {
+  cursorToolOnLoad: {
+    value: 0,
+    kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+  },
+  defaultUrl: {
+    value: 'compressed.tracemonkey-pldi-09.pdf',
+    kind: OptionKind.VIEWER
+  },
+  defaultZoomValue: {
+    value: '',
+    kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+  },
+  disableHistory: {
+    value: false,
+    kind: OptionKind.VIEWER
+  },
+  disablePageLabels: {
+    value: false,
+    kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+  },
+  enablePrintAutoRotate: {
+    value: false,
+    kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+  },
+  enableWebGL: {
+    value: false,
+    kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+  },
+  eventBusDispatchToDOM: {
+    value: false,
+    kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+  },
+  externalLinkRel: {
+    value: 'noopener noreferrer nofollow',
+    kind: OptionKind.VIEWER
+  },
+  externalLinkTarget: {
+    value: 0,
+    kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+  },
+  historyUpdateUrl: {
+    value: false,
+    kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+  },
+  imageResourcesPath: {
+    value: './images/',
+    kind: OptionKind.VIEWER
+  },
+  maxCanvasPixels: {
+    value: 16777216,
+    compatibility: _viewer_compatibility.viewerCompatibilityParams.maxCanvasPixels,
+    kind: OptionKind.VIEWER
+  },
+  pdfBugEnabled: {
+    value: false,
+    kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+  },
+  renderer: {
+    value: 'canvas',
+    kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+  },
+  renderInteractiveForms: {
+    value: false,
+    kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+  },
+  sidebarViewOnLoad: {
+    value: -1,
+    kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+  },
+  scrollModeOnLoad: {
+    value: -1,
+    kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+  },
+  spreadModeOnLoad: {
+    value: -1,
+    kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+  },
+  textLayerMode: {
+    value: 1,
+    kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+  },
+  useOnlyCssZoom: {
+    value: false,
+    kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+  },
+  viewOnLoad: {
+    value: 0,
+    kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+  },
+  cMapPacked: {
+    value: true,
+    kind: OptionKind.API
+  },
+  cMapUrl: {
+    value: '../web/cmaps/',
+    kind: OptionKind.API
+  },
+  disableAutoFetch: {
+    value: false,
+    kind: OptionKind.API + OptionKind.PREFERENCE
+  },
+  disableCreateObjectURL: {
+    value: false,
+    compatibility: _pdfjsLib.apiCompatibilityParams.disableCreateObjectURL,
+    kind: OptionKind.API
+  },
+  disableFontFace: {
+    value: false,
+    kind: OptionKind.API + OptionKind.PREFERENCE
+  },
+  disableRange: {
+    value: false,
+    kind: OptionKind.API + OptionKind.PREFERENCE
+  },
+  disableStream: {
+    value: false,
+    kind: OptionKind.API + OptionKind.PREFERENCE
+  },
+  isEvalSupported: {
+    value: true,
+    kind: OptionKind.API
+  },
+  maxImageSize: {
+    value: -1,
+    kind: OptionKind.API
+  },
+  pdfBug: {
+    value: false,
+    kind: OptionKind.API
+  },
+  postMessageTransfers: {
+    value: true,
+    kind: OptionKind.API
+  },
+  verbosity: {
+    value: 1,
+    kind: OptionKind.API
+  },
+  workerPort: {
+    value: null,
+    kind: OptionKind.WORKER
+  },
+  workerSrc: {
+    value: '../build/pdf.worker.js',
+    kind: OptionKind.WORKER
+  }
+};
+;
+const userOptions = Object.create(null);
+
+class AppOptions {
+  constructor() {
+    throw new Error('Cannot initialize AppOptions.');
+  }
+
+  static get(name) {
+    const userOption = userOptions[name];
+
+    if (userOption !== undefined) {
+      return userOption;
+    }
+
+    const defaultOption = defaultOptions[name];
+
+    if (defaultOption !== undefined) {
+      return defaultOption.compatibility || defaultOption.value;
+    }
+
+    return undefined;
+  }
+
+  static getAll(kind = null) {
+    const options = Object.create(null);
+
+    for (const name in defaultOptions) {
+      const defaultOption = defaultOptions[name];
+
+      if (kind) {
+        if ((kind & defaultOption.kind) === 0) {
+          continue;
+        }
+
+        if ((kind & OptionKind.PREFERENCE) !== 0) {
+          options[name] = defaultOption.value;
+          continue;
+        }
+      }
+
+      const userOption = userOptions[name];
+      options[name] = userOption !== undefined ? userOption : defaultOption.compatibility || defaultOption.value;
+    }
+
+    return options;
+  }
+
+  static set(name, value) {
+    userOptions[name] = value;
+  }
+
+  static remove(name) {
+    delete userOptions[name];
+  }
+
+}
+
+exports.AppOptions = AppOptions;
+
+/***/ }),
+/* 4 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
 let pdfjsLib;
 
 if (typeof window !== 'undefined' && window['pdfjs-dist/build/pdf']) {
   pdfjsLib = window['pdfjs-dist/build/pdf'];
 } else {
   pdfjsLib = require('../build/pdf.js');
 }
 
 module.exports = pdfjsLib;
 
 /***/ }),
-/* 4 */
+/* 5 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+let compatibilityParams = Object.create(null);
+;
+exports.viewerCompatibilityParams = Object.freeze(compatibilityParams);
+
+/***/ }),
+/* 6 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.PDFCursorTools = exports.CursorTool = void 0;
 
-var _grab_to_pan = __webpack_require__(5);
+var _grab_to_pan = __webpack_require__(7);
 
 const CursorTool = {
   SELECT: 0,
   HAND: 1,
   ZOOM: 2
 };
 exports.CursorTool = CursorTool;
 
@@ -3232,17 +3474,17 @@ class PDFCursorTools {
     });
   }
 
 }
 
 exports.PDFCursorTools = PDFCursorTools;
 
 /***/ }),
-/* 5 */
+/* 7 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
@@ -3395,17 +3637,17 @@ function isLeftMouseReleased(event) {
   }
 
   if (isChrome15OrOpera15plus || isSafari6plus) {
     return event.which === 0;
   }
 }
 
 /***/ }),
-/* 6 */
+/* 8 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
@@ -3532,30 +3774,30 @@ class PDFRenderingQueue {
     return true;
   }
 
 }
 
 exports.PDFRenderingQueue = PDFRenderingQueue;
 
 /***/ }),
-/* 7 */
+/* 9 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.PDFSidebar = exports.SidebarView = void 0;
 
 var _ui_utils = __webpack_require__(2);
 
-var _pdf_rendering_queue = __webpack_require__(6);
+var _pdf_rendering_queue = __webpack_require__(8);
 
 const UI_NOTIFICATION_CLASS = 'pdfSidebarNotification';
 const SidebarView = {
   UNKNOWN: -1,
   NONE: 0,
   THUMBS: 1,
   OUTLINE: 2,
   ATTACHMENTS: 3,
@@ -3901,250 +4143,16 @@ class PDFSidebar {
     });
   }
 
 }
 
 exports.PDFSidebar = PDFSidebar;
 
 /***/ }),
-/* 8 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
-  value: true
-});
-exports.OptionKind = exports.AppOptions = void 0;
-
-var _pdfjsLib = __webpack_require__(3);
-
-var _viewer_compatibility = __webpack_require__(9);
-
-const OptionKind = {
-  VIEWER: 'viewer',
-  API: 'api',
-  WORKER: 'worker'
-};
-exports.OptionKind = OptionKind;
-const defaultOptions = {
-  cursorToolOnLoad: {
-    value: 0,
-    kind: OptionKind.VIEWER
-  },
-  defaultUrl: {
-    value: 'compressed.tracemonkey-pldi-09.pdf',
-    kind: OptionKind.VIEWER
-  },
-  defaultZoomValue: {
-    value: '',
-    kind: OptionKind.VIEWER
-  },
-  disableHistory: {
-    value: false,
-    kind: OptionKind.VIEWER
-  },
-  disablePageLabels: {
-    value: false,
-    kind: OptionKind.VIEWER
-  },
-  enablePrintAutoRotate: {
-    value: false,
-    kind: OptionKind.VIEWER
-  },
-  enableWebGL: {
-    value: false,
-    kind: OptionKind.VIEWER
-  },
-  eventBusDispatchToDOM: {
-    value: false,
-    kind: OptionKind.VIEWER
-  },
-  externalLinkRel: {
-    value: 'noopener noreferrer nofollow',
-    kind: OptionKind.VIEWER
-  },
-  externalLinkTarget: {
-    value: 0,
-    kind: OptionKind.VIEWER
-  },
-  historyUpdateUrl: {
-    value: false,
-    kind: OptionKind.VIEWER
-  },
-  imageResourcesPath: {
-    value: './images/',
-    kind: OptionKind.VIEWER
-  },
-  maxCanvasPixels: {
-    value: 16777216,
-    compatibility: _viewer_compatibility.viewerCompatibilityParams.maxCanvasPixels,
-    kind: OptionKind.VIEWER
-  },
-  pdfBugEnabled: {
-    value: false,
-    kind: OptionKind.VIEWER
-  },
-  renderer: {
-    value: 'canvas',
-    kind: OptionKind.VIEWER
-  },
-  renderInteractiveForms: {
-    value: false,
-    kind: OptionKind.VIEWER
-  },
-  sidebarViewOnLoad: {
-    value: -1,
-    kind: OptionKind.VIEWER
-  },
-  scrollModeOnLoad: {
-    value: -1,
-    kind: OptionKind.VIEWER
-  },
-  spreadModeOnLoad: {
-    value: -1,
-    kind: OptionKind.VIEWER
-  },
-  textLayerMode: {
-    value: 1,
-    kind: OptionKind.VIEWER
-  },
-  useOnlyCssZoom: {
-    value: false,
-    kind: OptionKind.VIEWER
-  },
-  viewOnLoad: {
-    value: 0,
-    kind: OptionKind.VIEWER
-  },
-  cMapPacked: {
-    value: true,
-    kind: OptionKind.API
-  },
-  cMapUrl: {
-    value: '../web/cmaps/',
-    kind: OptionKind.API
-  },
-  disableAutoFetch: {
-    value: false,
-    kind: OptionKind.API
-  },
-  disableCreateObjectURL: {
-    value: false,
-    compatibility: _pdfjsLib.apiCompatibilityParams.disableCreateObjectURL,
-    kind: OptionKind.API
-  },
-  disableFontFace: {
-    value: false,
-    kind: OptionKind.API
-  },
-  disableRange: {
-    value: false,
-    kind: OptionKind.API
-  },
-  disableStream: {
-    value: false,
-    kind: OptionKind.API
-  },
-  isEvalSupported: {
-    value: true,
-    kind: OptionKind.API
-  },
-  maxImageSize: {
-    value: -1,
-    kind: OptionKind.API
-  },
-  pdfBug: {
-    value: false,
-    kind: OptionKind.API
-  },
-  postMessageTransfers: {
-    value: true,
-    kind: OptionKind.API
-  },
-  verbosity: {
-    value: 1,
-    kind: OptionKind.API
-  },
-  workerPort: {
-    value: null,
-    kind: OptionKind.WORKER
-  },
-  workerSrc: {
-    value: '../build/pdf.worker.js',
-    kind: OptionKind.WORKER
-  }
-};
-;
-const userOptions = Object.create(null);
-
-class AppOptions {
-  constructor() {
-    throw new Error('Cannot initialize AppOptions.');
-  }
-
-  static get(name) {
-    const userOption = userOptions[name];
-
-    if (userOption !== undefined) {
-      return userOption;
-    }
-
-    const defaultOption = defaultOptions[name];
-
-    if (defaultOption !== undefined) {
-      return defaultOption.compatibility || defaultOption.value;
-    }
-
-    return undefined;
-  }
-
-  static getAll(kind = null) {
-    const options = Object.create(null);
-
-    for (const name in defaultOptions) {
-      const defaultOption = defaultOptions[name];
-
-      if (kind && kind !== defaultOption.kind) {
-        continue;
-      }
-
-      const userOption = userOptions[name];
-      options[name] = userOption !== undefined ? userOption : defaultOption.compatibility || defaultOption.value;
-    }
-
-    return options;
-  }
-
-  static set(name, value) {
-    userOptions[name] = value;
-  }
-
-  static remove(name) {
-    delete userOptions[name];
-  }
-
-}
-
-exports.AppOptions = AppOptions;
-
-/***/ }),
-/* 9 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-let compatibilityParams = Object.create(null);
-;
-exports.viewerCompatibilityParams = Object.freeze(compatibilityParams);
-
-/***/ }),
 /* 10 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
@@ -4259,17 +4267,17 @@ exports.OverlayManager = OverlayManager;
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.PasswordPrompt = void 0;
 
 var _ui_utils = __webpack_require__(2);
 
-var _pdfjsLib = __webpack_require__(3);
+var _pdfjsLib = __webpack_require__(4);
 
 class PasswordPrompt {
   constructor(options, overlayManager, l10n = _ui_utils.NullL10n) {
     this.overlayName = options.overlayName;
     this.container = options.container;
     this.label = options.label;
     this.input = options.input;
     this.submitButton = options.submitButton;
@@ -4336,17 +4344,17 @@ exports.PasswordPrompt = PasswordPrompt;
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.PDFAttachmentViewer = void 0;
 
-var _pdfjsLib = __webpack_require__(3);
+var _pdfjsLib = __webpack_require__(4);
 
 class PDFAttachmentViewer {
   constructor({
     container,
     eventBus,
     downloadManager
   }) {
     this.container = container;
@@ -4486,17 +4494,17 @@ exports.PDFAttachmentViewer = PDFAttachm
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.PDFDocumentProperties = void 0;
 
 var _ui_utils = __webpack_require__(2);
 
-var _pdfjsLib = __webpack_require__(3);
+var _pdfjsLib = __webpack_require__(4);
 
 const DEFAULT_FIELD_CONTENT = '-';
 const NON_METRIC_LOCALES = ['en-us', 'en-lr', 'my'];
 const US_PAGE_NAMES = {
   '8.5x11': 'Letter',
   '8.5x14': 'Legal'
 };
 const METRIC_PAGE_NAMES = {
@@ -5020,17 +5028,17 @@ exports.PDFFindBar = PDFFindBar;
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.PDFFindController = exports.FindState = void 0;
 
 var _ui_utils = __webpack_require__(2);
 
-var _pdfjsLib = __webpack_require__(3);
+var _pdfjsLib = __webpack_require__(4);
 
 var _pdf_find_utils = __webpack_require__(16);
 
 const FindState = {
   FOUND: 0,
   NOT_FOUND: 1,
   WRAPPED: 2,
   PENDING: 3
@@ -6771,17 +6779,17 @@ exports.SimpleLinkService = SimpleLinkSe
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.PDFOutlineViewer = void 0;
 
-var _pdfjsLib = __webpack_require__(3);
+var _pdfjsLib = __webpack_require__(4);
 
 const DEFAULT_TITLE = '\u2013';
 
 class PDFOutlineViewer {
   constructor({
     container,
     linkService,
     eventBus
@@ -7766,21 +7774,21 @@ exports.PDFThumbnailViewer = PDFThumbnai
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.PDFThumbnailView = void 0;
 
-var _pdfjsLib = __webpack_require__(3);
+var _pdfjsLib = __webpack_require__(4);
 
 var _ui_utils = __webpack_require__(2);
 
-var _pdf_rendering_queue = __webpack_require__(6);
+var _pdf_rendering_queue = __webpack_require__(8);
 
 const MAX_NUM_SCALING_STEPS = 3;
 const THUMBNAIL_CANVAS_BORDER_WIDTH = 1;
 const THUMBNAIL_WIDTH = 98;
 
 const TempImageFactory = function TempImageFactoryClosure() {
   let tempCanvasCache = null;
   return {
@@ -7886,16 +7894,17 @@ class PDFThumbnailView {
       scale: 1,
       rotation: totalRotation
     });
     this.reset();
   }
 
   reset() {
     this.cancelRendering();
+    this.renderingState = _pdf_rendering_queue.RenderingStates.INITIAL;
     this.pageWidth = this.viewport.width;
     this.pageHeight = this.viewport.height;
     this.pageRatio = this.pageWidth / this.pageHeight;
     this.canvasHeight = this.canvasWidth / this.pageRatio | 0;
     this.scale = this.canvasWidth / this.pageWidth;
     this.div.removeAttribute('data-loaded');
     let ring = this.ring;
     let childNodes = ring.childNodes;
@@ -7934,17 +7943,16 @@ class PDFThumbnailView {
   }
 
   cancelRendering() {
     if (this.renderTask) {
       this.renderTask.cancel();
       this.renderTask = null;
     }
 
-    this.renderingState = _pdf_rendering_queue.RenderingStates.INITIAL;
     this.resume = null;
   }
 
   _getPageDrawContext(noCtxScale = false) {
     let canvas = document.createElement('canvas');
     this.canvas = canvas;
     canvas.mozOpaque = true;
     let ctx = canvas.getContext('2d', {
@@ -8168,17 +8176,17 @@ exports.PDFThumbnailView = PDFThumbnailV
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.PDFViewer = void 0;
 
 var _base_viewer = __webpack_require__(25);
 
-var _pdfjsLib = __webpack_require__(3);
+var _pdfjsLib = __webpack_require__(4);
 
 class PDFViewer extends _base_viewer.BaseViewer {
   get _setDocumentViewerElement() {
     return (0, _pdfjsLib.shadow)(this, '_setDocumentViewerElement', this.viewer);
   }
 
   _scrollIntoView({
     pageDiv,
@@ -8255,21 +8263,21 @@ exports.PDFViewer = PDFViewer;
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.BaseViewer = void 0;
 
 var _ui_utils = __webpack_require__(2);
 
-var _pdf_rendering_queue = __webpack_require__(6);
+var _pdf_rendering_queue = __webpack_require__(8);
 
 var _annotation_layer_builder = __webpack_require__(26);
 
-var _pdfjsLib = __webpack_require__(3);
+var _pdfjsLib = __webpack_require__(4);
 
 var _pdf_page_view = __webpack_require__(27);
 
 var _pdf_link_service = __webpack_require__(18);
 
 var _text_layer_builder = __webpack_require__(28);
 
 const DEFAULT_CACHE_SIZE = 10;
@@ -9306,17 +9314,17 @@ exports.BaseViewer = BaseViewer;
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.DefaultAnnotationLayerFactory = exports.AnnotationLayerBuilder = void 0;
 
-var _pdfjsLib = __webpack_require__(3);
+var _pdfjsLib = __webpack_require__(4);
 
 var _ui_utils = __webpack_require__(2);
 
 var _pdf_link_service = __webpack_require__(18);
 
 class AnnotationLayerBuilder {
   constructor({
     pageDiv,
@@ -9419,21 +9427,21 @@ exports.DefaultAnnotationLayerFactory = 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.PDFPageView = void 0;
 
 var _ui_utils = __webpack_require__(2);
 
-var _pdfjsLib = __webpack_require__(3);
-
-var _pdf_rendering_queue = __webpack_require__(6);
-
-var _viewer_compatibility = __webpack_require__(9);
+var _pdfjsLib = __webpack_require__(4);
+
+var _pdf_rendering_queue = __webpack_require__(8);
+
+var _viewer_compatibility = __webpack_require__(5);
 
 const MAX_CANVAS_PIXELS = _viewer_compatibility.viewerCompatibilityParams.maxCanvasPixels || 16777216;
 
 class PDFPageView {
   constructor(options) {
     let container = options.container;
     let defaultViewport = options.defaultViewport;
     this.id = options.id;
@@ -9510,16 +9518,17 @@ class PDFPageView {
       this.zoomLayer.remove();
     }
 
     this.zoomLayer = null;
   }
 
   reset(keepZoomLayer = false, keepAnnotations = false) {
     this.cancelRendering(keepAnnotations);
+    this.renderingState = _pdf_rendering_queue.RenderingStates.INITIAL;
     let div = this.div;
     div.style.width = Math.floor(this.viewport.width) + 'px';
     div.style.height = Math.floor(this.viewport.height) + 'px';
     let childNodes = div.childNodes;
     let currentZoomLayerNode = keepZoomLayer && this.zoomLayer || null;
     let currentAnnotationNode = keepAnnotations && this.annotationLayer && this.annotationLayer.div || null;
 
     for (let i = childNodes.length - 1; i >= 0; i--) {
@@ -9615,43 +9624,32 @@ class PDFPageView {
     if (this.zoomLayer) {
       this.cssTransform(this.zoomLayer.firstChild);
     }
 
     this.reset(true, true);
   }
 
   cancelRendering(keepAnnotations = false) {
-    const renderingState = this.renderingState;
-
     if (this.paintTask) {
       this.paintTask.cancel();
       this.paintTask = null;
     }
 
-    this.renderingState = _pdf_rendering_queue.RenderingStates.INITIAL;
     this.resume = null;
 
     if (this.textLayer) {
       this.textLayer.cancel();
       this.textLayer = null;
     }
 
     if (!keepAnnotations && this.annotationLayer) {
       this.annotationLayer.cancel();
       this.annotationLayer = null;
     }
-
-    if (renderingState !== _pdf_rendering_queue.RenderingStates.INITIAL) {
-      this.eventBus.dispatch('pagecancelled', {
-        source: this,
-        pageNumber: this.id,
-        renderingState
-      });
-    }
   }
 
   cssTransform(target, redrawAnnotations = false) {
     let width = this.viewport.width;
     let height = this.viewport.height;
     let div = this.div;
     target.style.width = target.parentNode.style.width = div.style.width = Math.floor(width) + 'px';
     target.style.height = target.parentNode.style.height = div.style.height = Math.floor(height) + 'px';
@@ -9990,17 +9988,17 @@ exports.PDFPageView = PDFPageView;
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.DefaultTextLayerFactory = exports.TextLayerBuilder = void 0;
 
 var _ui_utils = __webpack_require__(2);
 
-var _pdfjsLib = __webpack_require__(3);
+var _pdfjsLib = __webpack_require__(4);
 
 const EXPAND_DIVS_TIMEOUT = 300;
 
 class TextLayerBuilder {
   constructor({
     textLayerDiv,
     eventBus,
     pageIndex,
@@ -10017,19 +10015,17 @@ class TextLayerBuilder {
     this.pageIdx = pageIndex;
     this.pageNumber = this.pageIdx + 1;
     this.matches = [];
     this.viewport = viewport;
     this.textDivs = [];
     this.findController = findController;
     this.textLayerRenderTask = null;
     this.enhanceTextSelection = enhanceTextSelection;
-    this._boundEvents = Object.create(null);
-
-    this._bindEvents();
+    this._onUpdateTextLayerMatches = null;
 
     this._bindMouse();
   }
 
   _finishRendering() {
     this.renderingDone = true;
 
     if (!this.enhanceTextSelection) {
@@ -10065,23 +10061,38 @@ class TextLayerBuilder {
     });
     this.textLayerRenderTask.promise.then(() => {
       this.textLayerDiv.appendChild(textLayerFrag);
 
       this._finishRendering();
 
       this._updateMatches();
     }, function (reason) {});
+
+    if (!this._onUpdateTextLayerMatches) {
+      this._onUpdateTextLayerMatches = evt => {
+        if (evt.pageIndex === this.pageIdx || evt.pageIndex === -1) {
+          this._updateMatches();
+        }
+      };
+
+      this.eventBus.on('updatetextlayermatches', this._onUpdateTextLayerMatches);
+    }
   }
 
   cancel() {
     if (this.textLayerRenderTask) {
       this.textLayerRenderTask.cancel();
       this.textLayerRenderTask = null;
     }
+
+    if (this._onUpdateTextLayerMatches) {
+      this.eventBus.off('updatetextlayermatches', this._onUpdateTextLayerMatches);
+      this._onUpdateTextLayerMatches = null;
+    }
   }
 
   setTextContentStream(readableStream) {
     this.cancel();
     this.textContentStream = readableStream;
   }
 
   setTextContent(textContent) {
@@ -10274,50 +10285,16 @@ class TextLayerBuilder {
 
     const pageMatches = findController.pageMatches[pageIdx] || null;
     const pageMatchesLength = findController.pageMatchesLength[pageIdx] || null;
     this.matches = this._convertMatches(pageMatches, pageMatchesLength);
 
     this._renderMatches(this.matches);
   }
 
-  _bindEvents() {
-    const {
-      eventBus,
-      _boundEvents
-    } = this;
-
-    _boundEvents.pageCancelled = evt => {
-      if (evt.pageNumber !== this.pageNumber) {
-        return;
-      }
-
-      if (this.textLayerRenderTask) {
-        console.error('TextLayerBuilder._bindEvents: `this.cancel()` should ' + 'have been called when the page was reset, or rendering cancelled.');
-        return;
-      }
-
-      for (const name in _boundEvents) {
-        eventBus.off(name.toLowerCase(), _boundEvents[name]);
-        delete _boundEvents[name];
-      }
-    };
-
-    _boundEvents.updateTextLayerMatches = evt => {
-      if (evt.pageIndex !== this.pageIdx && evt.pageIndex !== -1) {
-        return;
-      }
-
-      this._updateMatches();
-    };
-
-    eventBus.on('pagecancelled', _boundEvents.pageCancelled);
-    eventBus.on('updatetextlayermatches', _boundEvents.updateTextLayerMatches);
-  }
-
   _bindMouse() {
     let div = this.textLayerDiv;
     let expandDivsTimer = null;
     div.addEventListener('mousedown', evt => {
       if (this.enhanceTextSelection && this.textLayerRenderTask) {
         this.textLayerRenderTask.expandTextDivs(true);
         return;
       }
@@ -10373,17 +10350,17 @@ exports.DefaultTextLayerFactory = Defaul
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.SecondaryToolbar = void 0;
 
 var _ui_utils = __webpack_require__(2);
 
-var _pdf_cursor_tools = __webpack_require__(4);
+var _pdf_cursor_tools = __webpack_require__(6);
 
 var _pdf_single_page_viewer = __webpack_require__(30);
 
 class SecondaryToolbar {
   constructor(options, mainContainer, eventBus) {
     this.toolbar = options.toolbar;
     this.toggleButton = options.toggleButton;
     this.toolbarButtonContainer = options.toolbarButtonContainer;
@@ -10689,17 +10666,17 @@ exports.SecondaryToolbar = SecondaryTool
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.PDFSinglePageViewer = void 0;
 
 var _base_viewer = __webpack_require__(25);
 
-var _pdfjsLib = __webpack_require__(3);
+var _pdfjsLib = __webpack_require__(4);
 
 class PDFSinglePageViewer extends _base_viewer.BaseViewer {
   constructor(options) {
     super(options);
     this.eventBus.on('pagesinit', evt => {
       this._ensurePageViewVisible();
     });
   }
@@ -11145,17 +11122,17 @@ exports.ViewHistory = ViewHistory;
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.FirefoxCom = exports.DownloadManager = void 0;
 
 __webpack_require__(34);
 
-var _pdfjsLib = __webpack_require__(3);
+var _pdfjsLib = __webpack_require__(4);
 
 var _preferences = __webpack_require__(35);
 
 var _app = __webpack_require__(1);
 
 ;
 
 let FirefoxCom = function FirefoxComClosure() {
@@ -11584,37 +11561,37 @@ Object.defineProperty(exports, "__esModu
   value: true
 });
 exports.BasePreferences = void 0;
 let defaultPreferences = null;
 
 function getDefaultPreferences() {
   if (!defaultPreferences) {
     defaultPreferences = Promise.resolve({
-      "viewOnLoad": 0,
+      "cursorToolOnLoad": 0,
       "defaultZoomValue": "",
-      "sidebarViewOnLoad": -1,
-      "cursorToolOnLoad": 0,
+      "disablePageLabels": false,
+      "enablePrintAutoRotate": false,
       "enableWebGL": false,
       "eventBusDispatchToDOM": false,
+      "externalLinkTarget": 0,
+      "historyUpdateUrl": false,
       "pdfBugEnabled": false,
-      "disableRange": false,
-      "disableStream": false,
+      "renderer": "canvas",
+      "renderInteractiveForms": false,
+      "sidebarViewOnLoad": -1,
+      "scrollModeOnLoad": -1,
+      "spreadModeOnLoad": -1,
+      "textLayerMode": 1,
+      "useOnlyCssZoom": false,
+      "viewOnLoad": 0,
       "disableAutoFetch": false,
       "disableFontFace": false,
-      "textLayerMode": 1,
-      "useOnlyCssZoom": false,
-      "externalLinkTarget": 0,
-      "renderer": "canvas",
-      "renderInteractiveForms": false,
-      "enablePrintAutoRotate": false,
-      "disablePageLabels": false,
-      "historyUpdateUrl": false,
-      "scrollModeOnLoad": -1,
-      "spreadModeOnLoad": -1
+      "disableRange": false,
+      "disableStream": false
     });
   }
 
   return defaultPreferences;
 }
 
 class BasePreferences {
   constructor() {
@@ -11730,17 +11707,17 @@ Object.defineProperty(exports, "__esModu
   value: true
 });
 exports.FirefoxPrintService = FirefoxPrintService;
 
 var _ui_utils = __webpack_require__(2);
 
 var _app = __webpack_require__(1);
 
-var _pdfjsLib = __webpack_require__(3);
+var _pdfjsLib = __webpack_require__(4);
 
 function composePage(pdfDocument, pageNumber, size, printContainer) {
   let canvas = document.createElement('canvas');
   const PRINT_RESOLUTION = 150;
   const PRINT_UNITS = PRINT_RESOLUTION / 72.0;
   canvas.width = Math.floor(size.width * PRINT_UNITS);
   canvas.height = Math.floor(size.height * PRINT_UNITS);
   canvas.style.width = Math.floor(size.width * _ui_utils.CSS_UNITS) + 'px';
--- a/browser/extensions/pdfjs/moz.yaml
+++ b/browser/extensions/pdfjs/moz.yaml
@@ -15,15 +15,15 @@ origin:
   description: Portable Document Format (PDF) viewer that is built with HTML5
 
   # Full URL for the package's homepage/etc
   # Usually different from repository url
   url: https://github.com/mozilla/pdf.js
 
   # Human-readable identifier for this version/release
   # Generally "version NNN", "tag SSS", "bookmark SSS"
-  release: version 2.1.266
+  release: version 2.2.15
 
   # The package's license, where possible using the mnemonic from
   # https://spdx.org/licenses/
   # Multiple licenses can be specified (as a YAML list)
   # A "LICENSE" file must exist containing the full license text
   license: Apache-2.0
--- a/build/moz.configure/init.configure
+++ b/build/moz.configure/init.configure
@@ -638,17 +638,17 @@ def split_triplet(triplet, allow_unknown
     # is not specified and emit
     #   CPU_TYPE-OPERATING_SYSTEM
     parts = triplet.split('-', 2)
     if len(parts) == 3:
         cpu, _, os = parts
     elif len(parts) == 2:
         cpu, os = parts
     else:
-        die("Unexpected triplet string: %s" % triplet)
+        raise ValueError("Unexpected triplet string: %s" % triplet)
 
     # Autoconf uses config.sub to validate and canonicalize those triplets,
     # but the granularity of its results has never been satisfying to our
     # use, so we've had our own, different, canonicalization. We've also
     # historically not been very consistent with how we use the canonicalized
     # values. Hopefully, this will help us make things better.
     # The tests are inherited from our decades-old autoconf-based configure,
     # which can probably be improved/cleaned up because they are based on a
@@ -682,17 +682,17 @@ def split_triplet(triplet, allow_unknown
         canonical_os = canonical_kernel = 'NetBSD'
     elif os.startswith('openbsd'):
         canonical_os = canonical_kernel = 'OpenBSD'
     elif os.startswith('solaris'):
         canonical_os = canonical_kernel = 'SunOS'
     elif allow_unknown:
         canonical_os = canonical_kernel = os
     else:
-        die('Unknown OS: %s' % os)
+        raise ValueError('Unknown OS: %s' % os)
 
     # The CPU granularity is probably not enough. Moving more things from
     # old-configure will tell us if we need more
     if cpu.endswith('86') or (cpu.startswith('i') and '86' in cpu):
         canonical_cpu = 'x86'
         endianness = 'little'
     elif cpu in ('x86_64', 'ia64'):
         canonical_cpu = cpu
@@ -732,17 +732,17 @@ def split_triplet(triplet, allow_unknown
         endianness = 'little'
     elif cpu == 'sh4':
         canonical_cpu = 'sh4'
         endianness = 'little'
     elif allow_unknown:
         canonical_cpu = cpu
         endianness = 'unknown'
     else:
-        die('Unknown CPU type: %s' % cpu)
+        raise ValueError('Unknown CPU type: %s' % cpu)
 
     def sanitize(cls, value):
         try:
             return cls(value)
         except (KeyError, ValueError):
             if allow_unknown:
                 return value
             raise
@@ -791,40 +791,51 @@ def config_sub(shell, triplet):
     return subprocess.check_output([shell, config_sub, triplet]).strip()
 
 
 @depends('--host', shell)
 @checking('for host system type', lambda h: h.alias)
 @imports('os')
 @imports('subprocess')
 @imports('sys')
+@imports(_from='__builtin__', _import='ValueError')
 def real_host(value, shell):
     if not value and sys.platform == 'win32':
         arch = (os.environ.get('PROCESSOR_ARCHITEW6432') or
                 os.environ.get('PROCESSOR_ARCHITECTURE'))
         if arch == 'AMD64':
             return split_triplet('x86_64-pc-mingw32')
         elif arch == 'x86':
             return split_triplet('i686-pc-mingw32')
 
     if not value:
         config_guess = os.path.join(os.path.dirname(__file__), '..',
                                     'autoconf', 'config.guess')
         host = subprocess.check_output([shell, config_guess]).strip()
+        try:
+            return split_triplet(host)
+        except ValueError:
+            pass
     else:
-        host = config_sub(shell, value[0])
+        host = value[0]
+
+    host = config_sub(shell, host)
 
-    return split_triplet(host)
+    try:
+        return split_triplet(host)
+    except ValueError as e:
+        die(e.message)
 
 
 host = help_host_target | real_host
 
 
 @depends('--target', real_host, shell, '--enable-project', '--enable-application')
 @checking('for target system type', lambda t: t.alias)
+@imports(_from='__builtin__', _import='ValueError')
 def real_target(value, host, shell, project, application):
     # Because --enable-project is implied by --enable-application, and
     # implied options are not currently handled during --help, which is
     # used get the build target in mozbuild.base, we manually check
     # whether --enable-application was given, and fall back to
     # --enable-project if not. Both can't be given contradictory values
     # under normal circumstances, so it's fine.
     if application:
@@ -841,19 +852,26 @@ def real_target(value, host, shell, proj
     target = value[0]
     if '-' not in target:
         if project == 'mobile/android':
             rest = 'unknown-linux-android'
             if target.startswith('arm'):
                 rest += 'eabi'
         else:
             cpu, rest = host.alias.split('-', 1)
-        return split_triplet('-'.join((target, rest)))
+        target = '-'.join((target, rest))
+        try:
+            return split_triplet(target)
+        except ValueError:
+            pass
 
-    return split_triplet(config_sub(shell, target))
+    try:
+        return split_triplet(config_sub(shell, target))
+    except ValueError as e:
+        die(e.message)
 
 
 target = help_host_target | real_target
 
 
 @depends(host, target)
 @checking('whether cross compiling')
 def cross_compiling(host, target):
new file mode 100644
--- /dev/null
+++ b/build/mozconfig.pgo
@@ -0,0 +1,7 @@
+case "$PERFHERDER_EXTRA_OPTIONS" in
+base-toolchains*)
+    ;;
+*)
+    export MOZ_PGO=1
+    ;;
+esac
--- a/configure.py
+++ b/configure.py
@@ -9,29 +9,37 @@ import itertools
 import logging
 import os
 import sys
 import textwrap
 
 
 base_dir = os.path.abspath(os.path.dirname(__file__))
 sys.path.insert(0, os.path.join(base_dir, 'python', 'mozbuild'))
-from mozbuild.configure import ConfigureSandbox
+from mozbuild.configure import (
+    ConfigureSandbox,
+    TRACE,
+)
 from mozbuild.pythonutil import iter_modules_in_path
 from mozbuild.backend.configenvironment import PartialConfigEnvironment
 from mozbuild.util import (
     indented_repr,
     encode,
 )
 import mozpack.path as mozpath
 
 
 def main(argv):
     config = {}
+
     sandbox = ConfigureSandbox(config, os.environ, argv)
+
+    if os.environ.get('MOZ_CONFIGURE_TRACE'):
+        sandbox._logger.setLevel(TRACE)
+
     sandbox.run(os.path.join(os.path.dirname(__file__), 'moz.configure'))
 
     if sandbox._help:
         return 0
 
     return config_status(config)
 
 
--- a/devtools/client/debugger/new/README.mozilla
+++ b/devtools/client/debugger/new/README.mozilla
@@ -1,13 +1,13 @@
 This is the debugger.html project output.
 See https://github.com/devtools-html/debugger.html
 
-Version 125
+Version 126
 
-Comparison: https://github.com/devtools-html/debugger.html/compare/release-124...release-125
+Comparison: https://github.com/devtools-html/debugger.html/compare/release-125...release-126
 
 Packages:
 - babel-plugin-transform-es2015-modules-commonjs @6.26.2
 - babel-preset-react @6.24.1
 - react @16.4.1
 - react-dom @16.4.1
 - webpack @3.12.0
--- a/devtools/client/debugger/new/dist/debugger.css
+++ b/devtools/client/debugger/new/dist/debugger.css
@@ -246,58 +246,58 @@ button.open-inspector {
   mask: url("resource://devtools/client/shared/components/reps/images/open-inspector.svg") no-repeat;
   display: inline-block;
   vertical-align: top;
   height: 15px;
   width: 15px;
   margin: 0 4px;
   padding: 0;
   border: none;
-  background-color: var(--comment-node-color);
+  background-color: var(--theme-icon-color);
   cursor: pointer;
 }
 
 .objectBox-accessible:hover .open-accessibility-inspector,
 .objectBox-node:hover .open-inspector,
 .objectBox-textNode:hover .open-inspector,
 .open-accessibility-inspector:hover,
 .open-inspector:hover {
-  background-color: var(--theme-highlight-blue);
+  background-color: var(--theme-icon-checked-color);
 }
 
 /******************************************************************************/
 /* Jump to definition button */
 
 button.jump-definition {
   mask: url("resource://devtools/client/shared/components/reps/images/jump-definition.svg") no-repeat;
   display: inline-block;
-  background-color: var(--comment-node-color);
+  background-color: var(--theme-icon-color);
   height: 16px;
   margin-left: 0.25em;
   vertical-align: middle;
 }
 
 .jump-definition:hover {
-  background-color: var(--theme-highlight-blue);
+  background-color: var(--theme-icon-checked-color);
 }
 
 /******************************************************************************/
 /* Invoke getter button */
 
 button.invoke-getter {
   mask: url("resource://devtools/client/shared/components/reps/images/input.svg") no-repeat;
   display: inline-block;
-  background-color: var(--comment-node-color);
+  background-color: var(--theme-icon-color);
   height: 10px;
   vertical-align: middle;
   border:none;
 }
 
 .invoke-getter:hover {
-  background-color: var(--theme-highlight-blue);
+  background-color: var(--theme-icon-checked-color);
 }
 
 /******************************************************************************/
 /* "more…" ellipsis */
 .more-ellipsis {
   color: var(--comment-node-color);
 }
 /* This Source Code Form is subject to the terms of the Mozilla Public
@@ -352,48 +352,45 @@ button.invoke-getter {
   padding-inline-start: 15px
 }
 
 .tree .tree-node[data-expandable="true"] {
   cursor: default;
 }
 
 .tree-node button.arrow {
-  background:url("resource://devtools/client/debugger/new/images/arrow.svg") no-repeat;
-  background-size:contain;
-  background-position:center center;
+  mask: url("resource://devtools/client/debugger/new/images/arrow.svg") no-repeat center;
+  mask-size: 10px;
+  vertical-align: -1px;
   width: 10px;
   height: 10px;
-  border:0;
-  padding:0;
+  border: 0;
+  padding: 0;
   margin-inline-start: 1px;
   margin-inline-end: 4px;
+  transform-origin: center center;
+  transition: transform 125ms var(--animation-curve);
+  background-color: var(--theme-icon-dimmed-color);
+}
+
+.tree-node button.arrow:not(.expanded) {
   transform: rotate(-90deg);
-  transform-origin: center center;
-  transition: transform 0.125s ease;
-  align-self: center;
-  -moz-context-properties: fill;
-  fill: var(--theme-splitter-color, #9B9B9B);
-}
-
-html[dir="rtl"] .tree-node button.arrow {
+}
+
+html[dir="rtl"] .tree-node button:not(.expanded) {
   transform: rotate(90deg);
 }
 
-.tree-node button.arrow.expanded.expanded {
-  transform: rotate(0deg);
- }
-
 .tree .tree-node.focused {
   color: white;
   background-color: var(--theme-selection-background, #0a84ff);
 }
 
 .tree-node.focused button.arrow {
-  fill: currentColor;
+  background-color: currentColor;
 }
 /* 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/. */
 
 .tree.object-inspector .node.object-node {
   display: inline-block;
 }
@@ -550,16 +547,18 @@ html[dir="rtl"] .tree-node button.arrow 
 
 :root {
   /* header height is 28px + 1px for its border */
   --editor-header-height: 29px;
   /* footer height is 24px + 1px for its border */
   --editor-footer-height: 25px;
   /* searchbar height is 24px + 1px for its top border */
   --editor-searchbar-height: 25px;
+  /* Remove once https://bugzilla.mozilla.org/show_bug.cgi?id=1520440 lands */
+  --theme-code-line-height: calc(15 / 11);
 }
 
 :root.theme-light,
 :root .theme-light {
   --search-overlays-semitransparent: rgba(221, 225, 228, 0.66);
   --popup-shadow-color: #d0d0d0;
 }
 
@@ -2313,17 +2312,17 @@ menuseparator {
 
 .source-footer > .commands > div.loader {
   vertical-align: top;
   width: 20px;
   margin: 0 4px;
 }
 
 .source-footer > .commands > .blackboxed > .img.blackBox {
-  background-color: var(--theme-highlight-blue);
+  background-color: var(--theme-icon-checked-color);
 }
 
 .source-footer .blackbox-summary,
 .source-footer .mapped-source,
 .source-footer .cursor-position {
   color: var(--theme-body-color);
   padding-right: 2.5px;
 }
@@ -2665,29 +2664,29 @@ menuseparator {
   color: var(--theme-comment);
 }
 /* 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/>. */
 
 .column-breakpoint {
   display: inline;
-  padding: 0;
-  padding-inline-end: 4px;
+  padding-inline-start: 1px;
+  padding-inline-end: 3px;
 }
 
 .column-breakpoint:hover {
   background-color: transparent;
 }
 
 .column-breakpoint svg {
-  display: inline;
+  display: inline-block;
   cursor: pointer;
-  height: 12px;
-  width: 9px;
+  height: 13px;
+  width: 11px;
   vertical-align: top;
 }
 
 .column-breakpoint.active svg {
   fill: var(--blue-50);
   stroke: var(--blue-60);
 }
 
@@ -2782,17 +2781,17 @@ menuseparator {
 }
 
 .theme-light {
   --theme-conditional-breakpoint-color: var(--theme-body-color);
 }
 
 /**
  * There's a known codemirror flex issue with chrome that this addresses.
- * BUG https://github.com/devtools-html/debugger.html/issues/63
+ * BUG https://github.com/firefox-devtools/debugger.html/issues/63
  */
 .editor-wrapper {
   position: absolute;
   height: calc(100% - var(--editor-header-height));
   width: calc(100% - 1px);
   top: var(--editor-header-height);
   left: 0px;
 }
@@ -2820,45 +2819,35 @@ html[dir="rtl"] .editor-mount {
 .theme-light .cm-s-mozilla .empty-line .CodeMirror-linenumber {
   color: var(--grey-40);
 }
 
 .theme-dark .cm-s-mozilla .empty-line .CodeMirror-linenumber {
   color: var(--grey-50);
 }
 
-:not(.empty-line):not(.new-breakpoint)
-  > .CodeMirror-gutter-wrapper:hover
-  > .CodeMirror-linenumber {
-  height: 13px;
-  color: var(--theme-body-color);
-  /* Add 1px offset to the background to match it
-    with the actual breakpoint image dimensions */
-  background: linear-gradient(
-    to bottom,
-    transparent 1px,
-    var(--gutter-hover-background-color) 0
-  );
-}
-
 .new-breakpoint .CodeMirror-linenumber {
   pointer-events: none;
 }
 
 :not(.empty-line):not(.new-breakpoint)
   > .CodeMirror-gutter-wrapper:hover
   > .CodeMirror-linenumber::after {
   content: "";
   position: absolute;
-  top: 1px;
-  height: 12px;
-  width: 9px;
+  /* paint below the number */
+  z-index: -1;
+  top: 0;
+  left: 0;
+  right: -7px;
+  bottom: 0;
+  height: 15px;
   background-color: var(--gutter-hover-background-color);
   mask: url("resource://devtools/client/debugger/new/images/breakpoint.svg") no-repeat;
-  mask-size: auto 12px;
+  mask-size: auto 15px;
   mask-position: right;
 }
 
 .editor-wrapper .breakpoints {
   position: absolute;
   top: 0;
   left: 0;
 }
@@ -2868,28 +2857,28 @@ html[dir="rtl"] .editor-mount {
   overflow: hidden;
 }
 
 .function-search .results {
   height: auto;
 }
 
 .editor.hit-marker {
-  height: 14px;
+  height: 15px;
 }
 
 .editor-wrapper .highlight-lines {
   background: var(--theme-selection-background-hover);
 }
 
 .editor.new-breakpoint svg {
   fill: var(--breakpoint-fill);
   stroke: var(--breakpoint-stroke);
   width: 60px;
-  height: 14px;
+  height: 15px;
   position: absolute;
   top: 0px;
   right: -4px;
 }
 
 .inline-bp {
   background-color: #9ddfff;
   width: 20px;
@@ -2924,36 +2913,33 @@ html[dir="rtl"] .editor-mount {
   stroke: var(--breakpoint-stroke-disabled);
   fill-opacity: 0.5;
 }
 
 .editor.column-breakpoint svg {
   fill: var(--theme-selection-background);
   vertical-align: middle;
   width: 17px;
-  height: 14px;
+  height: 15px;
 }
 
 .editor.column-breakpoint.breakpoint-disabled svg {
   opacity: 0.3;
 }
 
 .CodeMirror {
   width: 100%;
   height: 100%;
 }
 
 .editor-wrapper .editor-mount {
   width: 100%;
   background-color: var(--theme-body-background);
-}
-
-.CodeMirror-linenumber {
-  font-size: 11px;
-  line-height: 14px;
+  font-size: var(--theme-code-font-size);
+  line-height: var(--theme-code-line-height);
 }
 
 .folding-enabled .CodeMirror-linenumber {
   text-align: left;
   padding: 0 0 0 2px;
 }
 
 /* set the linenumber white when there is a breakpoint */
@@ -2964,20 +2950,16 @@ html[dir="rtl"] .editor-mount {
   color: white;
 }
 
 /* move the breakpoint below the other gutter elements */
 .new-breakpoint .CodeMirror-gutter-elt:nth-child(2) {
   z-index: 0;
 }
 
-.editor-wrapper .CodeMirror-line {
-  font-size: 11px;
-}
-
 .theme-dark .editor-wrapper .CodeMirror-line .cm-comment {
   color: var(--theme-comment);
 }
 
 .debug-expression,
 .new-debug-line .column-breakpoint {
   background-color: var(--debug-expression-background);
 }
@@ -3434,43 +3416,43 @@ html[dir="rtl"] .breakpoints-list .break
 
 .input-expression:not(:placeholder-shown) {
   font-family: var(--monospace-font-family);
 }
 /* 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/>. */
 
-.frames ul .frames-group .group,
-.frames ul .frames-group .group .location {
+.frames [role="list"] .frames-group .group,
+.frames [role="list"] .frames-group .group .location {
   font-weight: 500;
   cursor: default;
   /*
    * direction:rtl is set in Frames.css to overflow the location text from the
    * start. Here we need to reset it in order to display the framework icon
    * after the framework name.
    */
   direction: ltr;
 }
 
-.frames ul .frames-group.expanded .group,
-.frames ul .frames-group.expanded .group .location {
+.frames [role="list"] .frames-group.expanded .group,
+.frames [role="list"] .frames-group.expanded .group .location {
   color: var(--theme-highlight-blue);
 }
 
-.frames ul .frames-group .frames-list li {
+.frames [role="list"] .frames-group .frames-list [role="listitem"] {
   padding-left: 30px;
 }
 
-.frames ul .frames-group .frames-list {
+.frames [role="list"] .frames-group .frames-list {
   border-top: 1px solid var(--theme-splitter-color);
   border-bottom: 1px solid var(--theme-splitter-color);
 }
 
-.frames ul .frames-group.expanded .badge {
+.frames [role="list"] .frames-group.expanded .badge {
   color: var(--theme-highlight-blue);
 }
 
 .group-description-name {
   padding-left: 5px;
 }
 /* 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
@@ -3826,17 +3808,17 @@ html[dir="rtl"] .command-bar {
   color: var(--theme-highlight-blue);
 }
 
 .command-bar .subSettings {
   float: right;
 }
 
 .command-bar .active .disable-pausing {
-  background-color: var(--theme-highlight-blue);
+  background-color: var(--theme-icon-checked-color);
 }
 
 .bottom {
   border-bottom: none;
   background-color: var(--theme-body-background);
   border-top: 1px solid var(--theme-splitter-color);
   flex: none;
   height: var(--editor-footer-height);
@@ -3976,28 +3958,64 @@ html[dir="rtl"] .command-bar {
   position: absolute;
   top: 8px;
 }
 /* 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/>. */
 
 .event-listeners-content {
-	padding: 4px 20px;
+	padding-top: 4px;
+	padding-bottom: 4px;
+	padding-inline-start: 14px;
+	padding-inline-end: 20px;
 }
 
 .event-listeners-content ul {
 	padding: 0;
 	list-style-type: none;
 }
 
 .event-listener-group {
 	user-select: none;
 }
 
+.event-listener-header {
+	display: flex;
+	align-items: center;
+}
+
+.event-listener-expand {
+	border: none;
+	background: none;
+	padding: 4px 5px;
+	line-height: 12px;
+}
+
+.event-listener-expand:hover {
+	background: transparent;
+}
+
+.event-listener-group input[type="checkbox"] {
+	margin: 0px;
+	margin-inline-end: 4px;
+}
+
+.event-listener-label {
+	display: flex;
+	align-items: center;
+	padding-inline-start: 2px;
+	padding-inline-end: 10px;
+}
+
+.event-listener-category {
+	padding: 3px 0px;
+	line-height: 14px;
+}
+
 .event-listeners-content .arrow {
 	margin-inline-end: 0;
 }
 
 html[dir="ltr"] .event-listeners-content .arrow.expanded {
   transform: rotate(0deg);
 }
 
@@ -4006,19 +4024,26 @@ html[dir="rtl"] .event-listeners-content
 }
 
 .event-listener-event {
 	display: flex;
 	align-items: center;
 	margin-inline-start: 30px;
 }
 
+.event-listener-name {
+	line-height: 14px;
+	padding: 3px 0px;
+}
+
 .event-listener-event input {
 	margin-inline-end: 4px;
 	margin-inline-start: 0px;
+	margin-top: 0px;
+	margin-bottom: 0px;
 }
 /* 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/>. */
 
 .object-node.default-property {
   opacity: 0.6;
 }
@@ -4089,17 +4114,17 @@ html[dir="rtl"] .object-node {
   --breakpoint-expression-height: 2.4em;
 }
 
 /*
   We apply overflow to the container with the commandbar.
   This allows the commandbar to remain fixed when scrolling
   until the content completely ends. Not just the height of
   the wrapper.
-  Ref: https://github.com/devtools-html/debugger.html/issues/3426
+  Ref: https://github.com/firefox-devtools/debugger.html/issues/3426
 */
 
 .secondary-panes-wrapper {
   height: 100%;
   width: 100%;
   display: flex;
   flex-direction: column;
 }
@@ -4493,17 +4518,17 @@ html .welcomebox .toggle-button-end.coll
   background: var(--grey-70);
 }
 
 .theme-dark .result-list li.selected {
   background: var(--grey-70);
 }
 
 .result-list li .result-item-icon {
-  background-color: var(--theme-comment);
+  background-color: var(--theme-icon-dimmed-color);
 }
 
 .result-list li .icon {
   align-self: center;
   margin-inline-end: 14px;
   margin-inline-start: 4px;
 }
 
--- a/devtools/client/debugger/new/dist/parser-worker.js
+++ b/devtools/client/debugger/new/dist/parser-worker.js
@@ -557,58 +557,16 @@ function toKey(value) {
   return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
 }
 
 module.exports = toKey;
 
 
 /***/ }),
 
-/***/ 1127:
-/***/ (function(module, exports, __webpack_require__) {
-
-var baseIsEqual = __webpack_require__(799);
-
-/**
- * Performs a deep comparison between two values to determine if they are
- * equivalent.
- *
- * **Note:** This method supports comparing arrays, array buffers, booleans,
- * date objects, error objects, maps, numbers, `Object` objects, regexes,
- * sets, strings, symbols, and typed arrays. `Object` objects are compared
- * by their own, not inherited, enumerable properties. Functions and DOM
- * nodes are compared by strict equality, i.e. `===`.
- *
- * @static
- * @memberOf _
- * @since 0.1.0
- * @category Lang
- * @param {*} value The value to compare.
- * @param {*} other The other value to compare.
- * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
- * @example
- *
- * var object = { 'a': 1 };
- * var other = { 'a': 1 };
- *
- * _.isEqual(object, other);
- * // => true
- *
- * object === other;
- * // => false
- */
-function isEqual(value, other) {
-  return baseIsEqual(value, other);
-}
-
-module.exports = isEqual;
-
-
-/***/ }),
-
 /***/ 114:
 /***/ (function(module, exports, __webpack_require__) {
 
 var baseAssignValue = __webpack_require__(115),
     eq = __webpack_require__(97);
 
 /** Used for built-in method references. */
 var objectProto = Object.prototype;
@@ -1797,44 +1755,43 @@ var _findOutOfScopeLocations = __webpack
 var _findOutOfScopeLocations2 = _interopRequireDefault(_findOutOfScopeLocations);
 
 var _steps = __webpack_require__(1625);
 
 var _validate = __webpack_require__(1629);
 
 var _frameworks = __webpack_require__(1703);
 
-var _pausePoints = __webpack_require__(3612);
-
 var _mapExpression = __webpack_require__(3755);
 
 var _mapExpression2 = _interopRequireDefault(_mapExpression);
 
 var _devtoolsUtils = __webpack_require__(3651);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
-const { workerHandler } = _devtoolsUtils.workerUtils; /* 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/>. */
+/* 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/>. */
+
+const { workerHandler } = _devtoolsUtils.workerUtils;
 
 self.onmessage = workerHandler({
   findOutOfScopeLocations: _findOutOfScopeLocations2.default,
   getSymbols: _getSymbols.getSymbols,
   getScopes: _getScopes2.default,
   clearSymbols: _getSymbols.clearSymbols,
   clearScopes: _getScopes.clearScopes,
   clearASTs: _ast.clearASTs,
   hasSource: _sources.hasSource,
   setSource: _sources.setSource,
   clearSources: _sources.clearSources,
   getNextStep: _steps.getNextStep,
   hasSyntaxError: _validate.hasSyntaxError,
   getFramework: _frameworks.getFramework,
-  getPausePoints: _pausePoints.getPausePoints,
   mapExpression: _mapExpression2.default
 });
 
 /***/ }),
 
 /***/ 1620:
 /***/ (function(module, exports, __webpack_require__) {
 
@@ -22481,195 +22438,16 @@ class SimplePath {
     }
 
     return new SimplePath(this._ancestors.slice(0, -1).concat([{ node, key, index: siblingIndex }]));
   }
 }
 
 /***/ }),
 
-/***/ 3612:
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
-  value: true
-});
-exports.getPausePoints = getPausePoints;
-
-var _ast = __webpack_require__(1375);
-
-var _types = __webpack_require__(2268);
-
-var t = _interopRequireWildcard(_types);
-
-var _isEqual = __webpack_require__(1127);
-
-var _isEqual2 = _interopRequireDefault(_isEqual);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
-
-const isForStatement = node => t.isForStatement(node) || t.isForOfStatement(node); /* 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/>. */
-
-const isControlFlow = node => isForStatement(node) || t.isWhileStatement(node) || t.isIfStatement(node) || t.isSwitchCase(node) || t.isSwitchStatement(node) || t.isTryStatement(node) || t.isWithStatement(node);
-
-const isAssignment = node => t.isVariableDeclarator(node) || t.isAssignmentExpression(node) || t.isAssignmentPattern(node);
-
-const isImport = node => t.isImport(node) || t.isImportDeclaration(node);
-const isCall = node => t.isCallExpression(node) || t.isJSXElement(node);
-
-const inStepExpression = parent => t.isArrayExpression(parent) || t.isObjectProperty(parent) || t.isCallExpression(parent) || t.isJSXElement(parent) || t.isSequenceExpression(parent);
-
-const inExpression = (parent, grandParent) => inStepExpression(parent) || t.isJSXAttribute(grandParent) || t.isTemplateLiteral(parent);
-
-const isExport = node => t.isExportNamedDeclaration(node) || t.isExportDefaultDeclaration(node);
-
-// Finds the first call item in a step expression so that we can step
-// to the beginning of the list and either step in or over. e.g. [], x(), { }
-function isFirstCall(node, parentNode, grandParentNode) {
-  let children = [];
-  if (t.isArrayExpression(parentNode)) {
-    children = parentNode.elements;
-  }
-
-  if (t.isObjectProperty(parentNode)) {
-    children = grandParentNode.properties.map(({ value }) => value);
-  }
-
-  if (t.isSequenceExpression(parentNode)) {
-    children = parentNode.expressions;
-  }
-
-  if (t.isCallExpression(parentNode)) {
-    children = parentNode.arguments;
-  }
-
-  return children.find(child => isCall(child)) === node;
-}
-
-function getPausePoints(sourceId) {
-  const state = {};
-  (0, _ast.traverseAst)(sourceId, { enter: onEnter }, state);
-  return state;
-}
-
-/* eslint-disable complexity */
-function onEnter(node, ancestors, state) {
-  const parent = ancestors[ancestors.length - 1];
-  const parentNode = parent && parent.node;
-  const grandParent = ancestors[ancestors.length - 2];
-  const grandParentNode = grandParent && grandParent.node;
-  const startLocation = node.loc.start;
-
-  if (isImport(node) || t.isClassDeclaration(node) || isExport(node) || t.isDebuggerStatement(node) || t.isThrowStatement(node) || t.isBreakStatement(node) || t.isContinueStatement(node) || t.isReturnStatement(node)) {
-    return addStopPoint(state, startLocation);
-  }
-
-  if (isControlFlow(node)) {
-    addStopPoint(state, startLocation);
-
-    // We want to pause at tests so that we can pause at each iteration
-    // e.g `while (i++ < 3) { }`
-    const test = node.test || node.discriminant;
-    if (test) {
-      addStopPoint(state, test.loc.start);
-    }
-    return;
-  }
-
-  if (t.isBlockStatement(node) || t.isArrayExpression(node)) {
-    return addEmptyPoint(state, startLocation);
-  }
-
-  if (isAssignment(node)) {
-    // step at assignments unless the right side is a default assignment
-    // e.g. `( b = 2 ) => {}`
-    const defaultAssignment = t.isFunction(parentNode) && parent.key === "params";
-
-    return addPoint(state, startLocation, !defaultAssignment);
-  }
-
-  if (isCall(node)) {
-    let location = startLocation;
-
-    // When functions are chained, we want to use the property location
-    // e.g `foo().bar()`
-    if (t.isMemberExpression(node.callee)) {
-      location = node.callee.property.loc.start;
-    }
-
-    // NOTE: We want to skip all nested calls in expressions except for the
-    // first call in arrays and objects expression e.g. [], {}, call
-    const step = isFirstCall(node, parentNode, grandParentNode) || !inExpression(parentNode, grandParentNode);
-
-    // NOTE: we add a point at the beginning of the expression
-    // and each of the calls because the engine does not support
-    // column-based member expression calls.
-    addPoint(state, startLocation, { break: true, step });
-
-    if (location && !(0, _isEqual2.default)(location, startLocation)) {
-      addPoint(state, location, { break: true, step });
-    }
-
-    return;
-  }
-
-  if (t.isClassProperty(node)) {
-    return addBreakPoint(state, startLocation);
-  }
-
-  if (t.isFunction(node)) {
-    const { line, column } = node.loc.end;
-    addBreakPoint(state, startLocation);
-    return addEmptyPoint(state, { line, column: column - 1 });
-  }
-
-  if (!hasPoint(state, startLocation) && inStepExpression(parentNode)) {
-    return addEmptyPoint(state, startLocation);
-  }
-}
-
-function hasPoint(state, { line, column }) {
-  return state[line] && state[line][column];
-}
-
-function addPoint(state, location, types) {
-  if (typeof types === "boolean") {
-    types = { step: types, break: types };
-  }
-
-  const { line, column } = location;
-
-  if (!state[line]) {
-    state[line] = {};
-  }
-  state[line][column] = { types, location };
-  return state;
-}
-
-function addStopPoint(state, location) {
-  return addPoint(state, location, { break: true, step: true });
-}
-
-function addEmptyPoint(state, location) {
-  return addPoint(state, location, {});
-}
-
-function addBreakPoint(state, location) {
-  return addPoint(state, location, { break: true });
-}
-
-/***/ }),
-
 /***/ 3613:
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
--- a/devtools/client/debugger/new/dist/vendors.css
+++ b/devtools/client/debugger/new/dist/vendors.css
@@ -50,48 +50,45 @@
   padding-inline-start: 15px
 }
 
 .tree .tree-node[data-expandable="true"] {
   cursor: default;
 }
 
 .tree-node button.arrow {
-  background:url("resource://devtools/client/debugger/new/images/arrow.svg") no-repeat;
-  background-size:contain;
-  background-position:center center;
+  mask: url("resource://devtools/client/debugger/new/images/arrow.svg") no-repeat center;
+  mask-size: 10px;
+  vertical-align: -1px;
   width: 10px;
   height: 10px;
-  border:0;
-  padding:0;
+  border: 0;
+  padding: 0;
   margin-inline-start: 1px;
   margin-inline-end: 4px;
-  transform: rotate(-90deg);
   transform-origin: center center;
-  transition: transform 0.125s ease;
-  align-self: center;
-  -moz-context-properties: fill;
-  fill: var(--theme-splitter-color, #9B9B9B);
+  transition: transform 125ms var(--animation-curve);
+  background-color: var(--theme-icon-dimmed-color);
 }
 
-html[dir="rtl"] .tree-node button.arrow {
-  transform: rotate(90deg);
+.tree-node button.arrow:not(.expanded) {
+  transform: rotate(-90deg);
 }
 
-.tree-node button.arrow.expanded.expanded {
-  transform: rotate(0deg);
- }
+html[dir="rtl"] .tree-node button:not(.expanded) {
+  transform: rotate(90deg);
+}
 
 .tree .tree-node.focused {
   color: white;
   background-color: var(--theme-selection-background, #0a84ff);
 }
 
 .tree-node.focused button.arrow {
-  fill: currentColor;
+  background-color: currentColor;
 }
 /* vim:set ts=2 sw=2 sts=2 et: */
 /* 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/. */
 
 .split-box {
   display: flex;
--- a/devtools/client/debugger/new/dist/vendors.js
+++ b/devtools/client/debugger/new/dist/vendors.js
@@ -4809,16 +4809,20 @@ const { Component, createFactory } = _re
                                                        * 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/>. */
 
 __webpack_require__(3671);
 
 // depth
 const AUTO_EXPAND_DEPTH = 0;
 
+// Simplied selector targetting elements that can receive the focus,
+// full version at https://stackoverflow.com/questions/1599660.
+const FOCUSABLE_SELECTOR = ["a[href]:not([tabindex='-1'])", "button:not([disabled]):not([tabindex='-1'])", "iframe:not([tabindex='-1'])", "input:not([disabled]):not([tabindex='-1'])", "select:not([disabled]):not([tabindex='-1'])", "textarea:not([disabled]):not([tabindex='-1'])", "[tabindex]:not([tabindex='-1'])"].join(", ");
+
 /**
  * An arrow that displays whether its node is expanded (▼) or collapsed
  * (▶). When its node has no children, it is hidden.
  */
 class ArrowExpander extends Component {
   static get propTypes() {
     return {
       expanded: _propTypes2.default.bool
@@ -4846,34 +4850,114 @@ const treeIndent = _reactDomFactories2.d
 
 class TreeNode extends Component {
   static get propTypes() {
     return {
       id: _propTypes2.default.any.isRequired,
       index: _propTypes2.default.number.isRequired,
       depth: _propTypes2.default.number.isRequired,
       focused: _propTypes2.default.bool.isRequired,
+      active: _propTypes2.default.bool.isRequired,
       expanded: _propTypes2.default.bool.isRequired,
       item: _propTypes2.default.any.isRequired,
       isExpandable: _propTypes2.default.bool.isRequired,
       onClick: _propTypes2.default.func,
       renderItem: _propTypes2.default.func.isRequired
     };
   }
 
+  constructor(props) {
+    super(props);
+
+    this.treeNodeRef = _react2.default.createRef();
+
+    this._onKeyDown = this._onKeyDown.bind(this);
+  }
+
+  componentDidMount() {
+    // Make sure that none of the focusable elements inside the tree node
+    // container are tabbable if the tree node is not active. If the tree node
+    // is active and focus is outside its container, focus on the first
+    // focusable element inside.
+    const elms = this.getFocusableElements();
+    if (this.props.active) {
+      if (elms.length > 0 && !elms.includes(document.activeElement)) {
+        elms[0].focus();
+      }
+    } else {
+      elms.forEach(elm => elm.setAttribute("tabindex", "-1"));
+    }
+  }
+
   shouldComponentUpdate(nextProps) {
     return this.props.item !== nextProps.item || this.props.focused !== nextProps.focused || this.props.expanded !== nextProps.expanded;
   }
 
+  /**
+   * Get a list of all elements that are focusable with a keyboard inside the
+   * tree node.
+   */
+  getFocusableElements() {
+    return this.treeNodeRef.current ? Array.from(this.treeNodeRef.current.querySelectorAll(FOCUSABLE_SELECTOR)) : [];
+  }
+
+  /**
+   * Wrap and move keyboard focus to first/last focusable element inside the
+   * tree node to prevent the focus from escaping the tree node boundaries.
+   * element).
+   *
+   * @param  {DOMNode} current  currently focused element
+   * @param  {Boolean} back     direction
+   * @return {Boolean}          true there is a newly focused element.
+   */
+  _wrapMoveFocus(current, back) {
+    const elms = this.getFocusableElements();
+    let next;
+
+    if (elms.length === 0) {
+      return false;
+    }
+
+    if (back) {
+      if (elms.indexOf(current) === 0) {
+        next = elms[elms.length - 1];
+        next.focus();
+      }
+    } else if (elms.indexOf(current) === elms.length - 1) {
+      next = elms[0];
+      next.focus();
+    }
+
+    return !!next;
+  }
+
+  _onKeyDown(e) {
+    const { target, key, shiftKey } = e;
+
+    if (key !== "Tab") {
+      return;
+    }
+
+    const focusMoved = this._wrapMoveFocus(target, shiftKey);
+    if (focusMoved) {
+      // Focus was moved to the begining/end of the list, so we need to prevent
+      // the default focus change that would happen here.
+      e.preventDefault();
+    }
+
+    e.stopPropagation();
+  }
+
   render() {
     const {
       depth,
       id,
       item,
       focused,
+      active,
       expanded,
       renderItem,
       isExpandable
     } = this.props;
 
     const arrow = isExpandable ? ArrowExpanderFactory({
       item,
       expanded
@@ -4887,19 +4971,21 @@ class TreeNode extends Component {
       ariaExpanded = true;
     }
 
     const indents = Array.from({ length: depth }).fill(treeIndent);
     const items = indents.concat(renderItem(item, depth, focused, arrow, expanded));
 
     return _reactDomFactories2.default.div({
       id,
-      className: `tree-node${focused ? " focused" : ""}`,
+      className: `tree-node${focused ? " focused" : ""}${active ? " active" : ""}`,
       onClick: this.props.onClick,
+      onKeyDownCapture: active ? this._onKeyDown : null,
       role: "treeitem",
+      ref: this.treeNodeRef,
       "aria-level": depth + 1,
       "aria-expanded": ariaExpanded,
       "data-expandable": this.props.isExpandable
     }, ...items);
   }
 }
 
 const ArrowExpanderFactory = createFactory(ArrowExpander);
@@ -5123,16 +5209,18 @@ class Tree extends Component {
       //     onExpand(item: Item)
       //     onCollapse(item: Item)
       //
       // Example:
       //
       //     onExpand: item => dispatchExpandActionToRedux(item)
       onExpand: _propTypes2.default.func,
       onCollapse: _propTypes2.default.func,
+      // The currently active (keyboard) item, if any such item exists.
+      active: _propTypes2.default.any,
       // Optional event handler called with the current focused node when the
       // Enter key is pressed. Can be useful to allow further keyboard actions
       // within the tree node.
       onActivate: _propTypes2.default.func,
       isExpandable: _propTypes2.default.func,
       // Additional classes to add to the root element.
       className: _propTypes2.default.string,
       // style object to be applied to the root element.
@@ -5151,54 +5239,53 @@ class Tree extends Component {
 
   constructor(props) {
     super(props);
 
     this.state = {
       seen: new Set()
     };
 
+    this.treeRef = _react2.default.createRef();
+
     this._onExpand = oncePerAnimationFrame(this._onExpand).bind(this);
     this._onCollapse = oncePerAnimationFrame(this._onCollapse).bind(this);
     this._focusPrevNode = oncePerAnimationFrame(this._focusPrevNode).bind(this);
     this._focusNextNode = oncePerAnimationFrame(this._focusNextNode).bind(this);
     this._focusParentNode = oncePerAnimationFrame(this._focusParentNode).bind(this);
     this._focusFirstNode = oncePerAnimationFrame(this._focusFirstNode).bind(this);
     this._focusLastNode = oncePerAnimationFrame(this._focusLastNode).bind(this);
 
     this._autoExpand = this._autoExpand.bind(this);
     this._preventArrowKeyScrolling = this._preventArrowKeyScrolling.bind(this);
+    this._preventEvent = this._preventEvent.bind(this);
     this._dfs = this._dfs.bind(this);
     this._dfsFromRoots = this._dfsFromRoots.bind(this);
     this._focus = this._focus.bind(this);
+    this._activate = this._activate.bind(this);
     this._scrollNodeIntoView = this._scrollNodeIntoView.bind(this);
     this._onBlur = this._onBlur.bind(this);
     this._onKeyDown = this._onKeyDown.bind(this);
     this._nodeIsExpandable = this._nodeIsExpandable.bind(this);
-    this._activateNode = oncePerAnimationFrame(this._activateNode).bind(this);
   }
 
   componentDidMount() {
     this._autoExpand();
     if (this.props.focused) {
       this._scrollNodeIntoView(this.props.focused);
-      // Always keep the focus on the tree itself.
-      this.treeRef.focus();
     }
   }
 
   componentWillReceiveProps(nextProps) {
     this._autoExpand();
   }
 
   componentDidUpdate(prevProps, prevState) {
     if (this.props.focused && prevProps.focused !== this.props.focused) {
       this._scrollNodeIntoView(this.props.focused);
-      // Always keep the focus on the tree itself.
-      this.treeRef.focus();
     }
   }
 
   _autoExpand() {
     const { autoExpandDepth, autoExpandNodeChildrenLimit } = this.props;
     if (!autoExpandDepth) {
       return;
     }
@@ -5237,26 +5324,31 @@ class Tree extends Component {
   }
 
   _preventArrowKeyScrolling(e) {
     switch (e.key) {
       case "ArrowUp":
       case "ArrowDown":
       case "ArrowLeft":
       case "ArrowRight":
-        e.preventDefault();
-        e.stopPropagation();
-        if (e.nativeEvent) {
-          if (e.nativeEvent.preventDefault) {
-            e.nativeEvent.preventDefault();
-          }
-          if (e.nativeEvent.stopPropagation) {
-            e.nativeEvent.stopPropagation();
-          }
-        }
+        this._preventEvent(e);
+        break;
+    }
+  }
+
+  _preventEvent(e) {
+    e.preventDefault();
+    e.stopPropagation();
+    if (e.nativeEvent) {
+      if (e.nativeEvent.preventDefault) {
+        e.nativeEvent.preventDefault();
+      }
+      if (e.nativeEvent.stopPropagation) {
+        e.nativeEvent.stopPropagation();
+      }
     }
   }
 
   /**
    * Perform a pre-order depth-first search from item.
    */
   _dfs(item, maxDepth = Infinity, traversal = [], _depth = 0) {
     traversal.push({ item, depth: _depth });
@@ -5338,36 +5430,56 @@ class Tree extends Component {
    *                 to the top or the bottom of the scrollable container when
    *                 the element is off canvas.
    */
   _focus(item, options = {}) {
     const { preventAutoScroll } = options;
     if (item && !preventAutoScroll) {
       this._scrollNodeIntoView(item, options);
     }
+
+    if (this.props.active != undefined) {
+      this._activate(undefined);
+      if (this.treeRef.current !== document.activeElement) {
+        this.treeRef.current.focus();
+      }
+    }
+
     if (this.props.onFocus) {
       this.props.onFocus(item);
     }
   }
 
   /**
+   * Sets the passed in item to be the active item.
+   *
+   * @param {Object|undefined} item
+   *        The item to be activated, or undefined to activate no item.
+   */
+  _activate(item) {
+    if (this.props.onActivate) {
+      this.props.onActivate(item);
+    }
+  }
+
+  /**
    * Sets the passed in item to be the focused item.
    *
    * @param {Object|undefined} item
    *        The item to be scrolled to.
    *
    * @param {Object|undefined} options
    *        An options object which can contain:
    *          - dir: "up" or "down" to indicate if we should scroll the element
    *                 to the top or the bottom of the scrollable container when
    *                 the element is off canvas.
    */
   _scrollNodeIntoView(item, options = {}) {
     if (item !== undefined) {
-      const treeElement = this.treeRef;
+      const treeElement = this.treeRef.current;
       const element = document.getElementById(this.props.getKey(item));
 
       if (element) {
         const { top, bottom } = element.getBoundingClientRect();
         const closestScrolledParent = node => {
           if (node == null) {
             return null;
           }
@@ -5388,27 +5500,33 @@ class Tree extends Component {
         }
       }
     }
   }
 
   /**
    * Sets the state to have no focused item.
    */
-  _onBlur() {
-    if (!this.props.preventBlur) {
+  _onBlur(e) {
+    if (this.props.active != undefined) {
+      const { relatedTarget } = e;
+      if (!this.treeRef.current.contains(relatedTarget)) {
+        this._activate(undefined);
+      }
+    } else if (!this.props.preventBlur) {
       this._focus(undefined);
     }
   }
 
   /**
    * Handles key down events in the tree's container.
    *
    * @param {Event} e
    */
+  // eslint-disable-next-line complexity
   _onKeyDown(e) {
     if (this.props.focused == null) {
       return;
     }
 
     // Allow parent nodes to use navigation arrows with modifiers.
     if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {
       return;
@@ -5445,17 +5563,35 @@ class Tree extends Component {
         this._focusFirstNode();
         return;
 
       case "End":
         this._focusLastNode();
         return;
 
       case "Enter":
-        this._activateNode();
+      case " ":
+        if (this.treeRef.current === document.activeElement) {
+          this._preventEvent(e);
+          if (this.props.active !== this.props.focused) {
+            this._activate(this.props.focused);
+          }
+        }
+        return;
+
+      case "Escape":
+        this._preventEvent(e);
+        if (this.props.active != undefined) {
+          this._activate(undefined);
+        }
+
+        if (this.treeRef.current !== document.activeElement) {
+          this.treeRef.current.focus();
+        }
+        return;
     }
   }
 
   /**
    * Sets the previous node relative to the currently focused item, to focused.
    */
   _focusPrevNode() {
     // Start a depth first search and keep going until we reach the currently
@@ -5524,41 +5660,39 @@ class Tree extends Component {
   }
 
   _focusLastNode() {
     const traversal = this._dfsFromRoots();
     const lastIndex = traversal.length - 1;
     this._focus(traversal[lastIndex].item, { alignTo: "bottom" });
   }
 
-  _activateNode() {
-    if (this.props.onActivate) {
-      this.props.onActivate(this.props.focused);
-    }
-  }
-
   _nodeIsExpandable(item) {
     return this.props.isExpandable ? this.props.isExpandable(item) : !!this.props.getChildren(item).length;
   }
 
   render() {
     const traversal = this._dfsFromRoots();
-    const { focused } = this.props;
+    const { active, focused } = this.props;
 
     const nodes = traversal.map((v, i) => {
       const { item, depth } = traversal[i];
       const key = this.props.getKey(item, i);
       return TreeNodeFactory({
-        key,
+        // We make a key unique depending on whether the tree node is in active
+        // or inactive state to make sure that it is actually replaced and the
+        // tabbable state is reset.
+        key: `${key}-${active === item ? "active" : "inactive"}`,
         id: key,
         index: i,
         item,
         depth,
         renderItem: this.props.renderItem,
         focused: focused === item,
+        active: active === item,
         expanded: this.props.isExpanded(item),
         isExpandable: this._nodeIsExpandable(item),
         onExpand: this._onExpand,
         onCollapse: this._onCollapse,
         onClick: e => {
           // We can stop the propagation since click handler on the node can be
           // created in `renderItem`.
           e.stopPropagation();
@@ -5566,42 +5700,43 @@ class Tree extends Component {
           // Since the user just clicked the node, there's no need to check if
           // it should be scrolled into view.
           this._focus(item, { preventAutoScroll: true });
           if (this.props.isExpanded(item)) {
             this.props.onCollapse(item, e.altKey);
           } else {
             this.props.onExpand(item, e.altKey);
           }
+
+          // Focus should always remain on the tree container itself.
+          this.treeRef.current.focus();
         }
       });
     });
 
     const style = Object.assign({}, this.props.style || {});
 
     return _reactDomFactories2.default.div({
       className: `tree ${this.props.className ? this.props.className : ""}`,
-      ref: el => {
-        this.treeRef = el;
-      },
+      ref: this.treeRef,
       role: "tree",
       tabIndex: "0",
       onKeyDown: this._onKeyDown,
       onKeyPress: this._preventArrowKeyScrolling,
       onKeyUp: this._preventArrowKeyScrolling,
       onFocus: ({ nativeEvent }) => {
-        if (focused || !nativeEvent || !this.treeRef) {
+        if (focused || !nativeEvent || !this.treeRef.current) {
           return;
         }
 
         const { explicitOriginalTarget } = nativeEvent;
         // Only set default focus to the first tree node if the focus came
         // from outside the tree (e.g. by tabbing to the tree from other
         // external elements).
-        if (explicitOriginalTarget !== this.treeRef && !this.treeRef.contains(explicitOriginalTarget)) {
+        if (explicitOriginalTarget !== this.treeRef.current && !this.treeRef.current.contains(explicitOriginalTarget)) {
           this._focus(traversal[0].item);
         }
       },
       onBlur: this._onBlur,
       "aria-label": this.props.label,
       "aria-labelledby": this.props.labelledby,
       "aria-activedescendant": focused && this.props.getKey(focused),
       style
@@ -7560,24 +7695,24 @@ Svg.displayName = "Svg";
 
 module.exports = Svg;
 
 /***/ }),
 
 /***/ 3843:
 /***/ (function(module, exports) {
 
-module.exports = "<!-- 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/. --><svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 60 14\"><path d=\"M53.07.5H1.5a1 1 0 0 0-1 1v11a1 1 0 0 0 1 1h51.57a2 2 0 0 0 1.53-.7L59.3 7l-4.7-5.8a2 2 0 0 0-1.53-.7z\"></path></svg>"
+module.exports = "<!-- 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/. --><svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 60 15\"><path d=\"M53.07.5H1.5c-.54 0-1 .46-1 1v12c0 .54.46 1 1 1h51.57c.58 0 1.15-.26 1.53-.7l4.7-6.3-4.7-6.3c-.38-.44-.95-.7-1.53-.7z\"></path></svg>"
 
 /***/ }),
 
 /***/ 3844:
 /***/ (function(module, exports) {
 
-module.exports = "<svg viewBox=\"0 0 9 12\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><g id=\"columnmarkergroup\" stroke-width=\"1\" fill-rule=\"evenodd\"><polygon id=\"columnmarker\" points=\"0 0 4 0 9 6 4 12 0 12\"></polygon></g></svg>"
+module.exports = "<!-- 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/. --><svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 11 13\"><path d=\"M5.07.5H1.5c-.54 0-1 .46-1 1v10c0 .54.46 1 1 1h3.57c.58 0 1.15-.26 1.53-.7l3.7-5.3-3.7-5.3C6.22.76 5.65.5 5.07.5z\"></path></svg>"
 
 /***/ }),
 
 /***/ 4:
 /***/ (function(module, exports) {
 
 module.exports = __WEBPACK_EXTERNAL_MODULE_4__;
 
--- a/devtools/client/debugger/new/images/arrow.svg
+++ b/devtools/client/debugger/new/images/arrow.svg
@@ -1,6 +1,6 @@
 <!-- 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/. -->
-<svg viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg">
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10" width="10" height="10">
   <path d="M5 8c-.25 0-.35-.1-.65-.4l-3.1-3.35C.75 3.7 1.1 3 1.75 3h6.5c.65 0 1 .7.5 1.25L5.65 7.6c-.3.3-.4.4-.65.4z"/>
 </svg>
--- a/devtools/client/debugger/new/images/breakpoint.svg
+++ b/devtools/client/debugger/new/images/breakpoint.svg
@@ -1,6 +1,6 @@
 <!-- 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/. -->
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 14">
-  <path d="M53.07.5H1.5a1 1 0 0 0-1 1v11a1 1 0 0 0 1 1h51.57a2 2 0 0 0 1.53-.7L59.3 7l-4.7-5.8a2 2 0 0 0-1.53-.7z"/>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 15" width="60" height="15">
+  <path d="M53.07.5H1.5c-.54 0-1 .46-1 1v12c0 .54.46 1 1 1h51.57c.58 0 1.15-.26 1.53-.7l4.7-6.3-4.7-6.3c-.38-.44-.95-.7-1.53-.7z"/>
 </svg>
--- a/devtools/client/debugger/new/index.html
+++ b/devtools/client/debugger/new/index.html
@@ -19,9 +19,9 @@
     const { require } = BrowserLoader({
       baseURI: "resource://devtools/client/debugger/new",
       window,
     });
     Debugger = require("devtools/client/debugger/new/src/main");
   </script>
 </body>
 
-</html>
\ No newline at end of file
+</html>
--- a/devtools/client/debugger/new/packages/devtools-components/src/tests/__snapshots__/tree.js.snap
+++ b/devtools/client/debugger/new/packages/devtools-components/src/tests/__snapshots__/tree.js.snap
@@ -12,16 +12,265 @@ Array [
   "key-I",
   "key-D",
   "key-J",
   "key-M",
   "key-N",
 ]
 `;
 
+exports[`Tree active item - focus is inside the tree node and then blur 1`] = `
+"
+▼ A
+|  ▼ B
+|  |  ▼ E
+|  |  |    K
+|  |  |    [L anchor]
+|  |    F
+|  |    G
+|  ▼ C
+|  |    H
+|  |    I
+|  ▼ D
+|  |    J
+▼ M
+|  ▼ N
+|  |    O
+"
+`;
+
+exports[`Tree active item - focus is inside the tree node when possible 1`] = `
+"
+▼ A
+|  ▼ B
+|  |  ▼ E
+|  |  |    K
+|  |  |    [L anchor]
+|  |    F
+|  |    G
+|  ▼ C
+|  |    H
+|  |    I
+|  ▼ D
+|  |    J
+▼ M
+|  ▼ N
+|  |    O
+"
+`;
+
+exports[`Tree active item - focus is inside the tree node when possible 2`] = `
+"
+▼ A
+|  ▼ B
+|  |  ▼ E
+|  |  |    K
+|  |  |    [L anchor]
+|  |    F
+|  |    G
+|  ▼ C
+|  |    H
+|  |    I
+|  ▼ D
+|  |    J
+▼ M
+|  ▼ N
+|  |    O
+"
+`;
+
+exports[`Tree active item - navigate inside the tree node 1`] = `
+"
+▼ A
+|  ▼ B
+|  |  ▼ E
+|  |  |    K
+|  |  |    [L anchor]
+|  |    F
+|  |    G
+|  ▼ C
+|  |    H
+|  |    I
+|  ▼ D
+|  |    J
+▼ M
+|  ▼ N
+|  |    O
+"
+`;
+
+exports[`Tree active item - navigate inside the tree node 2`] = `
+"
+▼ A
+|  ▼ B
+|  |  ▼ E
+|  |  |    K
+|  |  |    [L anchor]
+|  |    F
+|  |    G
+|  ▼ C
+|  |    H
+|  |    I
+|  ▼ D
+|  |    J
+▼ M
+|  ▼ N
+|  |    O
+"
+`;
+
+exports[`Tree active item - navigate inside the tree node 3`] = `
+"
+▼ A
+|  ▼ B
+|  |  ▼ E
+|  |  |    K
+|  |  |    [L anchor]
+|  |    F
+|  |    G
+|  ▼ C
+|  |    H
+|  |    I
+|  ▼ D
+|  |    J
+▼ M
+|  ▼ N
+|  |    O
+"
+`;
+
+exports[`Tree active item - renders as expected when clicking away 1`] = `
+"
+▼ A
+|  ▼ B
+|  |  ▼ E
+|  |  |    K
+|  |  |    L
+|  |    F
+|  |    [G]
+|  ▼ C
+|  |    H
+|  |    I
+|  ▼ D
+|  |    J
+▼ M
+|  ▼ N
+|  |    O
+"
+`;
+
+exports[`Tree active item - renders as expected when clicking away 2`] = `
+"
+▶︎ [A]
+▼ M
+|  ▼ N
+|  |    O
+"
+`;
+
+exports[`Tree active item - renders as expected when moving away with keyboard 1`] = `
+"
+▼ A
+|  ▼ B
+|  |  ▼ E
+|  |  |    K
+|  |  |    [L]
+|  |    F
+|  |    G
+|  ▼ C
+|  |    H
+|  |    I
+|  ▼ D
+|  |    J
+▼ M
+|  ▼ N
+|  |    O
+"
+`;
+
+exports[`Tree active item - renders as expected when tree blurs 1`] = `
+"
+▼ A
+|  ▼ B
+|  |  ▼ E
+|  |  |    K
+|  |  |    L
+|  |    F
+|  |    [G]
+|  ▼ C
+|  |    H
+|  |    I
+|  ▼ D
+|  |    J
+▼ M
+|  ▼ N
+|  |    O
+"
+`;
+
+exports[`Tree active item - renders as expected when tree blurs 2`] = `
+"
+▼ A
+|  ▼ B
+|  |  ▼ E
+|  |  |    K
+|  |  |    L
+|  |    F
+|  |    [G]
+|  ▼ C
+|  |    H
+|  |    I
+|  ▼ D
+|  |    J
+▼ M
+|  ▼ N
+|  |    O
+"
+`;
+
+exports[`Tree active item - renders as expected when using keyboard and Enter 1`] = `
+"
+▼ A
+|  ▼ B
+|  |  ▼ E
+|  |  |    K
+|  |  |    [L]
+|  |    F
+|  |    G
+|  ▼ C
+|  |    H
+|  |    I
+|  ▼ D
+|  |    J
+▼ M
+|  ▼ N
+|  |    O
+"
+`;
+
+exports[`Tree active item - renders as expected when using keyboard and Space 1`] = `
+"
+▼ A
+|  ▼ B
+|  |  ▼ E
+|  |  |    K
+|  |  |    [L]
+|  |    F
+|  |    G
+|  ▼ C
+|  |    H
+|  |    I
+|  ▼ D
+|  |    J
+▼ M
+|  ▼ N
+|  |    O
+"
+`;
+
 exports[`Tree ignores key strokes when pressing modifiers 1`] = `
 "
 ▼ A
 |  ▼ B
 |  |  ▼ E
 |  |  |    K
 |  |  |    [L]
 |  |    F
--- a/devtools/client/debugger/new/packages/devtools-components/src/tests/tree.js
+++ b/devtools/client/debugger/new/packages/devtools-components/src/tests/tree.js
@@ -15,19 +15,21 @@ const Tree = createFactory(Components.Tr
 function mountTree(overrides = {}) {
   return mount(
     createFactory(
       class container extends Component {
         constructor(props) {
           super(props);
           const state = {
             expanded: overrides.expanded || new Set(),
-            focused: overrides.focused
+            focused: overrides.focused,
+            active: overrides.active
           };
           delete overrides.focused;
+          delete overrides.active;
           this.state = state;
         }
 
         render() {
           return Tree(
             Object.assign(
               {
                 getParent: x => TEST_TREE.parent[x],
@@ -44,32 +46,38 @@ function mountTree(overrides = {}) {
                 getRoots: () => ["A", "M"],
                 getKey: x => `key-${x}`,
                 itemHeight: 1,
                 onFocus: x => {
                   this.setState(previousState => {
                     return { focused: x };
                   });
                 },
+                onActivate: x => {
+                  this.setState(previousState => {
+                    return { active: x };
+                  });
+                },
                 onExpand: x => {
                   this.setState(previousState => {
                     const expanded = new Set(previousState.expanded);
                     expanded.add(x);
                     return { expanded };
                   });
                 },
                 onCollapse: x => {
                   this.setState(previousState => {
                     const expanded = new Set(previousState.expanded);
                     expanded.delete(x);
                     return { expanded };
                   });
                 },
                 isExpanded: x => this.state && this.state.expanded.has(x),
-                focused: this.state.focused
+                focused: this.state.focused,
+                active: this.state.active
               },
               overrides
             )
           );
         }
       }
     )()
   );
@@ -190,16 +198,170 @@ describe("Tree", () => {
 
   it("renders as expected when passed autoDepth:1", () => {
     const wrapper = mountTree({
       autoExpandDepth: 1
     });
     expect(formatTree(wrapper)).toMatchSnapshot();
   });
 
+  it("active item - renders as expected when clicking away", () => {
+    const wrapper = mountTree({
+      expanded: new Set("ABCDEFGHIJKLMNO".split("")),
+      focused: "G",
+      active: "G"
+    });
+    expect(formatTree(wrapper)).toMatchSnapshot();
+    expect(wrapper.find(".active").prop("id")).toBe("key-G");
+
+    getTreeNodes(wrapper)
+      .first()
+      .simulate("click");
+    expect(formatTree(wrapper)).toMatchSnapshot();
+    expect(wrapper.find(".focused").prop("id")).toBe("key-A");
+    expect(wrapper.find(".active").exists()).toBe(false);
+  });
+
+  it("active item - renders as expected when tree blurs", () => {
+    const wrapper = mountTree({
+      expanded: new Set("ABCDEFGHIJKLMNO".split("")),
+      focused: "G",
+      active: "G"
+    });
+    expect(formatTree(wrapper)).toMatchSnapshot();
+    expect(wrapper.find(".active").prop("id")).toBe("key-G");
+
+    wrapper.simulate("blur");
+    expect(formatTree(wrapper)).toMatchSnapshot();
+    expect(wrapper.find(".active").exists()).toBe(false);
+  });
+
+  it("active item - renders as expected when moving away with keyboard", () => {
+    const wrapper = mountTree({
+      expanded: new Set("ABCDEFGHIJKLMNO".split("")),
+      focused: "L",
+      active: "L"
+    });
+    expect(formatTree(wrapper)).toMatchSnapshot();
+    expect(wrapper.find(".active").prop("id")).toBe("key-L");
+
+    simulateKeyDown(wrapper, "ArrowUp");
+    expect(wrapper.find(".active").exists()).toBe(false);
+  });
+
+  it("active item - renders as expected when using keyboard and Enter", () => {
+    const wrapper = mountTree({
+      expanded: new Set("ABCDEFGHIJKLMNO".split("")),
+      focused: "L"
+    });
+    wrapper.getDOMNode().focus();
+    expect(formatTree(wrapper)).toMatchSnapshot();
+    expect(wrapper.find(".active").exists()).toBe(false);
+
+    simulateKeyDown(wrapper, "Enter");
+    expect(wrapper.find(".active").prop("id")).toBe("key-L");
+
+    expect(wrapper.getDOMNode().ownerDocument.activeElement).toBe(
+      wrapper.getDOMNode()
+    );
+
+    simulateKeyDown(wrapper, "Escape");
+    expect(wrapper.find(".active").exists()).toBe(false);
+    expect(wrapper.getDOMNode().ownerDocument.activeElement).toBe(
+      wrapper.getDOMNode()
+    );
+  });
+
+  it("active item - renders as expected when using keyboard and Space", () => {
+    const wrapper = mountTree({
+      expanded: new Set("ABCDEFGHIJKLMNO".split("")),
+      focused: "L"
+    });
+    wrapper.getDOMNode().focus();
+    expect(formatTree(wrapper)).toMatchSnapshot();
+    expect(wrapper.find(".active").exists()).toBe(false);
+
+    simulateKeyDown(wrapper, " ");
+    expect(wrapper.find(".active").prop("id")).toBe("key-L");
+
+    simulateKeyDown(wrapper, "Escape");
+    expect(wrapper.find(".active").exists()).toBe(false);
+  });
+
+  it("active item - focus is inside the tree node when possible", () => {
+    const wrapper = mountTree({
+      expanded: new Set("ABCDEFGHIJKLMNO".split("")),
+      focused: "L",
+      renderItem: renderItemWithFocusableContent
+    });
+    wrapper.getDOMNode().focus();
+    expect(formatTree(wrapper)).toMatchSnapshot();
+    expect(wrapper.find(".active").exists()).toBe(false);
+    expect(wrapper.getDOMNode().ownerDocument.activeElement).toBe(
+      wrapper.getDOMNode()
+    );
+
+    simulateKeyDown(wrapper, "Enter");
+    expect(wrapper.find(".active").prop("id")).toBe("key-L");
+    expect(formatTree(wrapper)).toMatchSnapshot();
+    expect(wrapper.getDOMNode().ownerDocument.activeElement).toBe(
+      wrapper.find("#active-anchor").getDOMNode()
+    );
+  });
+
+  it("active item - navigate inside the tree node", () => {
+    const wrapper = mountTree({
+      expanded: new Set("ABCDEFGHIJKLMNO".split("")),
+      focused: "L",
+      renderItem: renderItemWithFocusableContent
+    });
+    wrapper.getDOMNode().focus();
+    simulateKeyDown(wrapper, "Enter");
+    expect(formatTree(wrapper)).toMatchSnapshot();
+    expect(wrapper.find(".active").prop("id")).toBe("key-L");
+    expect(wrapper.getDOMNode().ownerDocument.activeElement).toBe(
+      wrapper.find("#active-anchor").getDOMNode()
+    );
+
+    simulateKeyDown(wrapper, "Tab");
+    expect(formatTree(wrapper)).toMatchSnapshot();
+    expect(wrapper.find(".active").prop("id")).toBe("key-L");
+    expect(wrapper.getDOMNode().ownerDocument.activeElement).toBe(
+      wrapper.find("#active-anchor").getDOMNode()
+    );
+
+    simulateKeyDown(wrapper, "Tab", { shiftKey: true });
+    expect(formatTree(wrapper)).toMatchSnapshot();
+    expect(wrapper.find(".active").prop("id")).toBe("key-L");
+    expect(wrapper.getDOMNode().ownerDocument.activeElement).toBe(
+      wrapper.find("#active-anchor").getDOMNode()
+    );
+  });
+
+  it("active item - focus is inside the tree node and then blur", () => {
+    const wrapper = mountTree({
+      expanded: new Set("ABCDEFGHIJKLMNO".split("")),
+      focused: "L",
+      renderItem: renderItemWithFocusableContent
+    });
+    wrapper.getDOMNode().focus();
+    simulateKeyDown(wrapper, "Enter");
+    expect(formatTree(wrapper)).toMatchSnapshot();
+    expect(wrapper.find(".active").prop("id")).toBe("key-L");
+    expect(wrapper.getDOMNode().ownerDocument.activeElement).toBe(
+      wrapper.find("#active-anchor").getDOMNode()
+    );
+
+    wrapper.find("#active-anchor").simulate("blur");
+    expect(wrapper.find(".active").exists()).toBe(false);
+    expect(wrapper.getDOMNode().ownerDocument.activeElement).toBe(
+      wrapper.getDOMNode().ownerDocument.body
+    );
+  });
+
   it("renders as expected when given a focused item", () => {
     const wrapper = mountTree({
       expanded: new Set("ABCDEFGHIJKLMNO".split("")),
       focused: "G"
     });
     expect(formatTree(wrapper)).toMatchSnapshot();
     expect(wrapper.getDOMNode().getAttribute("aria-activedescendant")).toBe(
       "key-G"
@@ -507,75 +669,39 @@ describe("Tree", () => {
 
   it("focus treeRef when a node is clicked", () => {
     const wrapper = mountTree({
       expanded: new Set("ABCDEFGHIJKLMNO".split(""))
     });
     const treeRef = wrapper
       .find("Tree")
       .first()
-      .instance().treeRef;
+      .instance().treeRef.current;
     treeRef.focus = jest.fn();
 
     getTreeNodes(wrapper)
       .first()
       .simulate("click");
     expect(treeRef.focus.mock.calls).toHaveLength(1);
   });
 
   it("doesn't focus treeRef when focused is null", () => {
     const wrapper = mountTree({
       expanded: new Set("ABCDEFGHIJKLMNO".split("")),
       focused: "A"
     });
     const treeRef = wrapper
       .find("Tree")
       .first()
-      .instance().treeRef;
+      .instance().treeRef.current;
     treeRef.focus = jest.fn();
     wrapper.simulate("blur");
     expect(treeRef.focus.mock.calls).toHaveLength(0);
   });
 
-  it("calls onActivate when expected", () => {
-    const onActivate = jest.fn();
-
-    const wrapper = mountTree({
-      expanded: new Set("ABCDEFGHIJKLMNO".split("")),
-      focused: "A",
-      onActivate
-    });
-
-    simulateKeyDown(wrapper, "Enter");
-    expect(onActivate.mock.calls).toHaveLength(1);
-    expect(onActivate.mock.calls[0][0]).toBe("A");
-
-    simulateKeyDown(wrapper, "Enter");
-    expect(onActivate.mock.calls).toHaveLength(2);
-    expect(onActivate.mock.calls[1][0]).toBe("A");
-
-    simulateKeyDown(wrapper, "ArrowDown");
-    simulateKeyDown(wrapper, "Enter");
-    expect(onActivate.mock.calls).toHaveLength(3);
-    expect(onActivate.mock.calls[2][0]).toBe("B");
-
-    wrapper.simulate("blur");
-    simulateKeyDown(wrapper, "Enter");
-    expect(onActivate.mock.calls).toHaveLength(3);
-  });
-
-  it("does not throw when onActivate is undefined and Enter is pressed", () => {
-    const wrapper = mountTree({
-      expanded: new Set("ABCDEFGHIJKLMNO".split("")),
-      focused: "A"
-    });
-
-    simulateKeyDown(wrapper, "Enter");
-  });
-
   it("ignores key strokes when pressing modifiers", () => {
     const wrapper = mountTree({
       expanded: new Set("ABCDEFGHIJKLMNO".split("")),
       focused: "L"
     });
     expect(formatTree(wrapper)).toMatchSnapshot();
     expect(wrapper.getDOMNode().getAttribute("aria-activedescendant")).toBe(
       "key-L"
@@ -648,24 +774,38 @@ describe("Tree", () => {
     expect(nodes.at(1).prop("data-expandable")).toBe(false);
   });
 });
 
 function getTreeNodes(wrapper) {
   return wrapper.find(".tree-node");
 }
 
-function simulateKeyDown(wrapper, key) {
+function simulateKeyDown(wrapper, key, options) {
   wrapper.simulate("keydown", {
     key,
     preventDefault: () => {},
-    stopPropagation: () => {}
+    stopPropagation: () => {},
+    ...options
   });
 }
 
+function renderItemWithFocusableContent(x, depth, focused, arrow) {
+  const children = [arrow, focused ? "[" : null, x];
+  if (x === "L") {
+    children.push(dom.a({ id: "active-anchor", href: "#" }, " anchor"));
+  }
+
+  if (focused) {
+    children.push("]");
+  }
+
+  return dom.div({}, ...children);
+}
+
 /*
  * Takes an Enzyme wrapper (obtained with mount/mount/…) and
  * returns a stringified version of the Tree, e.g.
  *
  *   ▼ A
  *   |   ▼ B
  *   |   |   ▼ E
  *   |   |   |   K
--- a/devtools/client/debugger/new/packages/devtools-components/src/tree.css
+++ b/devtools/client/debugger/new/packages/devtools-components/src/tree.css
@@ -50,41 +50,38 @@
   padding-inline-start: 15px
 }
 
 .tree .tree-node[data-expandable="true"] {
   cursor: default;
 }
 
 .tree-node button.arrow {
-  background:url(/images/arrow.svg) no-repeat;
-  background-size:contain;
-  background-position:center center;
+  mask: url(/images/arrow.svg) no-repeat center;
+  mask-size: 10px;
+  vertical-align: -1px;
   width: 10px;
   height: 10px;
-  border:0;
-  padding:0;
+  border: 0;
+  padding: 0;
   margin-inline-start: 1px;
   margin-inline-end: 4px;
-  transform: rotate(-90deg);
   transform-origin: center center;
-  transition: transform 0.125s ease;
-  align-self: center;
-  -moz-context-properties: fill;
-  fill: var(--theme-splitter-color, #9B9B9B);
+  transition: transform 125ms var(--animation-curve);
+  background-color: var(--theme-icon-dimmed-color);
 }
 
-html[dir="rtl"] .tree-node button.arrow {
-  transform: rotate(90deg);
+.tree-node button.arrow:not(.expanded) {
+  transform: rotate(-90deg);
 }
 
-.tree-node button.arrow.expanded.expanded {
-  transform: rotate(0deg);
- }
+html[dir="rtl"] .tree-node button:not(.expanded) {
+  transform: rotate(90deg);
+}
 
 .tree .tree-node.focused {
   color: white;
   background-color: var(--theme-selection-background, #0a84ff);
 }
 
 .tree-node.focused button.arrow {
-  fill: currentColor;
+  background-color: currentColor;
 }
--- a/devtools/client/debugger/new/packages/devtools-components/src/tree.js
+++ b/devtools/client/debugger/new/packages/devtools-components/src/tree.js
@@ -7,16 +7,28 @@ const { Component, createFactory } = Rea
 import dom from "react-dom-factories";
 import PropTypes from "prop-types";
 
 require("./tree.css");
 
 // depth
 const AUTO_EXPAND_DEPTH = 0;
 
+// Simplied selector targetting elements that can receive the focus,
+// full version at https://stackoverflow.com/questions/1599660.
+const FOCUSABLE_SELECTOR = [
+  "a[href]:not([tabindex='-1'])",
+  "button:not([disabled]):not([tabindex='-1'])",
+  "iframe:not([tabindex='-1'])",
+  "input:not([disabled]):not([tabindex='-1'])",
+  "select:not([disabled]):not([tabindex='-1'])",
+  "textarea:not([disabled]):not([tabindex='-1'])",
+  "[tabindex]:not([tabindex='-1'])"
+].join(", ");
+
 /**
  * An arrow that displays whether its node is expanded (▼) or collapsed
  * (▶). When its node has no children, it is hidden.
  */
 class ArrowExpander extends Component {
   static get propTypes() {
     return {
       expanded: PropTypes.bool
@@ -44,38 +56,122 @@ const treeIndent = dom.span({ className:
 
 class TreeNode extends Component {
   static get propTypes() {
     return {
       id: PropTypes.any.isRequired,
       index: PropTypes.number.isRequired,
       depth: PropTypes.number.isRequired,
       focused: PropTypes.bool.isRequired,
+      active: PropTypes.bool.isRequired,
       expanded: PropTypes.bool.isRequired,
       item: PropTypes.any.isRequired,
       isExpandable: PropTypes.bool.isRequired,
       onClick: PropTypes.func,
       renderItem: PropTypes.func.isRequired
     };
   }
 
+  constructor(props) {
+    super(props);
+
+    this.treeNodeRef = React.createRef();
+
+    this._onKeyDown = this._onKeyDown.bind(this);
+  }
+
+  componentDidMount() {
+    // Make sure that none of the focusable elements inside the tree node
+    // container are tabbable if the tree node is not active. If the tree node
+    // is active and focus is outside its container, focus on the first
+    // focusable element inside.
+    const elms = this.getFocusableElements();
+    if (this.props.active) {
+      if (elms.length > 0 && !elms.includes(document.activeElement)) {
+        elms[0].focus();
+      }
+    } else {
+      elms.forEach(elm => elm.setAttribute("tabindex", "-1"));
+    }
+  }
+
   shouldComponentUpdate(nextProps) {
     return (
       this.props.item !== nextProps.item ||
       this.props.focused !== nextProps.focused ||
       this.props.expanded !== nextProps.expanded
     );
   }
 
+  /**
+   * Get a list of all elements that are focusable with a keyboard inside the
+   * tree node.
+   */
+  getFocusableElements() {
+    return this.treeNodeRef.current
+      ? Array.from(
+          this.treeNodeRef.current.querySelectorAll(FOCUSABLE_SELECTOR)
+        )
+      : [];
+  }
+
+  /**
+   * Wrap and move keyboard focus to first/last focusable element inside the
+   * tree node to prevent the focus from escaping the tree node boundaries.
+   * element).
+   *
+   * @param  {DOMNode} current  currently focused element
+   * @param  {Boolean} back     direction
+   * @return {Boolean}          true there is a newly focused element.
+   */
+  _wrapMoveFocus(current, back) {
+    const elms = this.getFocusableElements();
+    let next;
+
+    if (elms.length === 0) {
+      return false;
+    }
+
+    if (back) {
+      if (elms.indexOf(current) === 0) {
+        next = elms[elms.length - 1];
+        next.focus();
+      }
+    } else if (elms.indexOf(current) === elms.length - 1) {
+      next = elms[0];
+      next.focus();
+    }
+
+    return !!next;
+  }
+
+  _onKeyDown(e) {
+    const { target, key, shiftKey } = e;
+
+    if (key !== "Tab") {
+      return;
+    }
+
+    const focusMoved = this._wrapMoveFocus(target, shiftKey);
+    if (focusMoved) {
+      // Focus was moved to the begining/end of the list, so we need to prevent
+      // the default focus change that would happen here.
+      e.preventDefault();
+    }
+
+    e.stopPropagation();
+  }
+
   render() {
     const {
       depth,
       id,
       item,
       focused,
+      active,
       expanded,
       renderItem,
       isExpandable
     } = this.props;
 
     const arrow = isExpandable
       ? ArrowExpanderFactory({
           item,
@@ -94,19 +190,23 @@ class TreeNode extends Component {
     const indents = Array.from({ length: depth }).fill(treeIndent);
     const items = indents.concat(
       renderItem(item, depth, focused, arrow, expanded)
     );
 
     return dom.div(
       {
         id,
-        className: `tree-node${focused ? " focused" : ""}`,
+        className: `tree-node${focused ? " focused" : ""}${
+          active ? " active" : ""
+        }`,
         onClick: this.props.onClick,
+        onKeyDownCapture: active ? this._onKeyDown : null,
         role: "treeitem",
+        ref: this.treeNodeRef,
         "aria-level": depth + 1,
         "aria-expanded": ariaExpanded,
         "data-expandable": this.props.isExpandable
       },
       ...items
     );
   }
 }
@@ -332,16 +432,18 @@ class Tree extends Component {
       //     onExpand(item: Item)
       //     onCollapse(item: Item)
       //
       // Example:
       //
       //     onExpand: item => dispatchExpandActionToRedux(item)
       onExpand: PropTypes.func,
       onCollapse: PropTypes.func,
+      // The currently active (keyboard) item, if any such item exists.
+      active: PropTypes.any,
       // Optional event handler called with the current focused node when the
       // Enter key is pressed. Can be useful to allow further keyboard actions
       // within the tree node.
       onActivate: PropTypes.func,
       isExpandable: PropTypes.func,
       // Additional classes to add to the root element.
       className: PropTypes.string,
       // style object to be applied to the root element.
@@ -360,58 +462,57 @@ class Tree extends Component {
 
   constructor(props) {
     super(props);
 
     this.state = {
       seen: new Set()
     };
 
+    this.treeRef = React.createRef();
+
     this._onExpand = oncePerAnimationFrame(this._onExpand).bind(this);
     this._onCollapse = oncePerAnimationFrame(this._onCollapse).bind(this);
     this._focusPrevNode = oncePerAnimationFrame(this._focusPrevNode).bind(this);
     this._focusNextNode = oncePerAnimationFrame(this._focusNextNode).bind(this);
     this._focusParentNode = oncePerAnimationFrame(this._focusParentNode).bind(
       this
     );
     this._focusFirstNode = oncePerAnimationFrame(this._focusFirstNode).bind(
       this
     );
     this._focusLastNode = oncePerAnimationFrame(this._focusLastNode).bind(this);
 
     this._autoExpand = this._autoExpand.bind(this);
     this._preventArrowKeyScrolling = this._preventArrowKeyScrolling.bind(this);
+    this._preventEvent = this._preventEvent.bind(this);
     this._dfs = this._dfs.bind(this);
     this._dfsFromRoots = this._dfsFromRoots.bind(this);
     this._focus = this._focus.bind(this);
+    this._activate = this._activate.bind(this);
     this._scrollNodeIntoView = this._scrollNodeIntoView.bind(this);
     this._onBlur = this._onBlur.bind(this);
     this._onKeyDown = this._onKeyDown.bind(this);
     this._nodeIsExpandable = this._nodeIsExpandable.bind(this);
-    this._activateNode = oncePerAnimationFrame(this._activateNode).bind(this);
   }
 
   componentDidMount() {
     this._autoExpand();
     if (this.props.focused) {
       this._scrollNodeIntoView(this.props.focused);
-      // Always keep the focus on the tree itself.
-      this.treeRef.focus();
     }
   }
 
   componentWillReceiveProps(nextProps) {
     this._autoExpand();
   }
 
   componentDidUpdate(prevProps, prevState) {
     if (this.props.focused && prevProps.focused !== this.props.focused) {
       this._scrollNodeIntoView(this.props.focused);
-      // Always keep the focus on the tree itself.
-      this.treeRef.focus();
     }
   }
 
   _autoExpand() {
     const { autoExpandDepth, autoExpandNodeChildrenLimit } = this.props;
     if (!autoExpandDepth) {
       return;
     }
@@ -453,26 +554,31 @@ class Tree extends Component {
   }
 
   _preventArrowKeyScrolling(e) {
     switch (e.key) {
       case "ArrowUp":
       case "ArrowDown":
       case "ArrowLeft":
       case "ArrowRight":
-        e.preventDefault();
-        e.stopPropagation();
-        if (e.nativeEvent) {
-          if (e.nativeEvent.preventDefault) {
-            e.nativeEvent.preventDefault();
-          }
-          if (e.nativeEvent.stopPropagation) {
-            e.nativeEvent.stopPropagation();
-          }
-        }
+        this._preventEvent(e);
+        break;
+    }
+  }
+
+  _preventEvent(e) {
+    e.preventDefault();
+    e.stopPropagation();
+    if (e.nativeEvent) {
+      if (e.nativeEvent.preventDefault) {
+        e.nativeEvent.preventDefault();
+      }
+      if (e.nativeEvent.stopPropagation) {
+        e.nativeEvent.stopPropagation();
+      }
     }
   }
 
   /**
    * Perform a pre-order depth-first search from item.
    */
   _dfs(item, maxDepth = Infinity, traversal = [], _depth = 0) {
     traversal.push({ item, depth: _depth });
@@ -554,36 +660,56 @@ class Tree extends Component {
    *                 to the top or the bottom of the scrollable container when
    *                 the element is off canvas.
    */
   _focus(item, options = {}) {
     const { preventAutoScroll } = options;
     if (item && !preventAutoScroll) {
       this._scrollNodeIntoView(item, options);
     }
+
+    if (this.props.active != undefined) {
+      this._activate(undefined);
+      if (this.treeRef.current !== document.activeElement) {
+        this.treeRef.current.focus();
+      }
+    }
+
     if (this.props.onFocus) {
       this.props.onFocus(item);
     }
   }
 
   /**
+   * Sets the passed in item to be the active item.
+   *
+   * @param {Object|undefined} item
+   *        The item to be activated, or undefined to activate no item.
+   */
+  _activate(item) {
+    if (this.props.onActivate) {
+      this.props.onActivate(item);
+    }
+  }
+
+  /**
    * Sets the passed in item to be the focused item.
    *
    * @param {Object|undefined} item
    *        The item to be scrolled to.
    *
    * @param {Object|undefined} options
    *        An options object which can contain:
    *          - dir: "up" or "down" to indicate if we should scroll the element
    *                 to the top or the bottom of the scrollable container when
    *                 the element is off canvas.
    */
   _scrollNodeIntoView(item, options = {}) {
     if (item !== undefined) {
-      const treeElement = this.treeRef;
+      const treeElement = this.treeRef.current;
       const element = document.getElementById(this.props.getKey(item));
 
       if (element) {
         const { top, bottom } = element.getBoundingClientRect();
         const closestScrolledParent = node => {
           if (node == null) {
             return null;
           }
@@ -611,27 +737,33 @@ class Tree extends Component {
         }
       }
     }
   }
 
   /**
    * Sets the state to have no focused item.
    */
-  _onBlur() {
-    if (!this.props.preventBlur) {
+  _onBlur(e) {
+    if (this.props.active != undefined) {
+      const { relatedTarget } = e;
+      if (!this.treeRef.current.contains(relatedTarget)) {
+        this._activate(undefined);
+      }
+    } else if (!this.props.preventBlur) {
       this._focus(undefined);
     }
   }
 
   /**
    * Handles key down events in the tree's container.
    *
    * @param {Event} e
    */
+  // eslint-disable-next-line complexity
   _onKeyDown(e) {
     if (this.props.focused == null) {
       return;
     }
 
     // Allow parent nodes to use navigation arrows with modifiers.
     if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {
       return;
@@ -674,17 +806,35 @@ class Tree extends Component {
         this._focusFirstNode();
         return;
 
       case "End":
         this._focusLastNode();
         return;
 
       case "Enter":
-        this._activateNode();
+      case " ":
+        if (this.treeRef.current === document.activeElement) {
+          this._preventEvent(e);
+          if (this.props.active !== this.props.focused) {
+            this._activate(this.props.focused);
+          }
+        }
+        return;
+
+      case "Escape":
+        this._preventEvent(e);
+        if (this.props.active != undefined) {
+          this._activate(undefined);
+        }
+
+        if (this.treeRef.current !== document.activeElement) {
+          this.treeRef.current.focus();
+        }
+        return;
     }
   }
 
   /**
    * Sets the previous node relative to the currently focused item, to focused.
    */
   _focusPrevNode() {
     // Start a depth first search and keep going until we reach the currently
@@ -753,43 +903,41 @@ class Tree extends Component {
   }
 
   _focusLastNode() {
     const traversal = this._dfsFromRoots();
     const lastIndex = traversal.length - 1;
     this._focus(traversal[lastIndex].item, { alignTo: "bottom" });
   }
 
-  _activateNode() {
-    if (this.props.onActivate) {
-      this.props.onActivate(this.props.focused);
-    }
-  }
-
   _nodeIsExpandable(item) {
     return this.props.isExpandable
       ? this.props.isExpandable(item)
       : !!this.props.getChildren(item).length;
   }
 
   render() {
     const traversal = this._dfsFromRoots();
-    const { focused } = this.props;
+    const { active, focused } = this.props;
 
     const nodes = traversal.map((v, i) => {
       const { item, depth } = traversal[i];
       const key = this.props.getKey(item, i);
       return TreeNodeFactory({
-        key,
+        // We make a key unique depending on whether the tree node is in active
+        // or inactive state to make sure that it is actually replaced and the
+        // tabbable state is reset.
+        key: `${key}-${active === item ? "active" : "inactive"}`,
         id: key,
         index: i,
         item,
         depth,
         renderItem: this.props.renderItem,
         focused: focused === item,
+        active: active === item,
         expanded: this.props.isExpanded(item),
         isExpandable: this._nodeIsExpandable(item),
         onExpand: this._onExpand,
         onCollapse: this._onCollapse,
         onClick: e => {
           // We can stop the propagation since click handler on the node can be
           // created in `renderItem`.
           e.stopPropagation();
@@ -797,45 +945,46 @@ class Tree extends Component {
           // Since the user just clicked the node, there's no need to check if
           // it should be scrolled into view.
           this._focus(item, { preventAutoScroll: true });
           if (this.props.isExpanded(item)) {
             this.props.onCollapse(item, e.altKey);
           } else {
             this.props.onExpand(item, e.altKey);
           }
+
+          // Focus should always remain on the tree container itself.
+          this.treeRef.current.focus();
         }
       });
     });
 
     const style = Object.assign({}, this.props.style || {});
 
     return dom.div(
       {
         className: `tree ${this.props.className ? this.props.className : ""}`,
-        ref: el => {
-          this.treeRef = el;
-        },
+        ref: this.treeRef,
         role: "tree",
         tabIndex: "0",
         onKeyDown: this._onKeyDown,
         onKeyPress: this._preventArrowKeyScrolling,
         onKeyUp: this._preventArrowKeyScrolling,
         onFocus: ({ nativeEvent }) => {
-          if (focused || !nativeEvent || !this.treeRef) {
+          if (focused || !nativeEvent || !this.treeRef.current) {
             return;
           }
 
           const { explicitOriginalTarget } = nativeEvent;
           // Only set default focus to the first tree node if the focus came
           // from outside the tree (e.g. by tabbing to the tree from other
           // external elements).
           if (
-            explicitOriginalTarget !== this.treeRef &&
-            !this.treeRef.contains(explicitOriginalTarget)
+            explicitOriginalTarget !== this.treeRef.current &&
+            !this.treeRef.current.contains(explicitOriginalTarget)
           ) {
             this._focus(traversal[0].item);
           }
         },
         onBlur: this._onBlur,
         "aria-label": this.props.label,
         "aria-labelledby": this.props.labelledby,
         "aria-activedescendant": focused && this.props.getKey(focused),
--- a/devtools/client/debugger/new/packages/devtools-reps/README.md
+++ b/devtools/client/debugger/new/packages/devtools-reps/README.md
@@ -40,17 +40,17 @@ Supported types:
 
 `Grip` is a client representation of a remote JS object and is used as an input object for this rep component.
 
 ## Getting started
 
 You need to clone the debugger.html repository, then install dependencies, for which you'll need the [Yarn](https://yarnpkg.com/en/) tool:
 
 ```
-git clone https://github.com/devtools-html/debugger.html.git
+git clone https://github.com/firefox-devtools/debugger.html.git
 cd debugger.html
 yarn install
 ```
 
 Once everything is installed, you can start the development server with:
 
 ```bash
 cd packages/devtools-reps/
@@ -90,15 +90,15 @@ The Reps project was ported to Github Ja
 ```bash
 git log --before "2017-1-17" devtools/client/shared/components/reps
 ```
 
 They were first moved to the [devtools-reps][gh-devtools-reps] repository, then to the [devtools-core][gh-devtools-core] one, before being migrated to this repository.
 
 [history]: https://github.com/mozilla/gecko-dev/commits/master/devtools/client/shared/components/reps
 [gh-devtools-reps]:
-https://github.com/devtools-html/reps/commits/master
+https://github.com/firefox-devtools/reps/commits/master
 [gh-devtools-core]:
-https://github.com/devtools-html/devtools-core/commits/5ba3d6f6a44def9978a983edd6f2f89747dca2c7/packages/devtools-reps
+https://github.com/firefox-devtools/devtools-core/commits/5ba3d6f6a44def9978a983edd6f2f89747dca2c7/packages/devtools-reps
 
 ## License
 
 [MPL 2](./LICENSE)
--- a/devtools/client/debugger/new/packages/devtools-reps/package.json
+++ b/devtools/client/debugger/new/packages/devtools-reps/package.json
@@ -1,25 +1,25 @@
 {
   "name": "devtools-reps",
   "version": "0.23.0",
   "description": "Devtools Reps",
   "main": "src/index.js",
   "scripts": {
     "start": "node bin/dev-server.js",
     "lint-js": "eslint src",
-    "firefox": "./node_modules/.bin/start-firefox --start --location https://devtools-html.github.io/debugger-examples/",
+    "firefox": "./node_modules/.bin/start-firefox --start --location https://firefox-devtools.github.io/debugger-examples/",
     "chrome": "./node_modules/.bin/start-chrome",
     "license-check": "devtools-license-check",
     "test": "jest --projects jest.config.js"
   },
   "author": "",
   "license": "MPL-2.0",
   "repository": {
-    "url": "git://github.com/devtools-html/reps.git",
+    "url": "git://github.com/firefox-devtools/reps.git",
     "type": "git"
   },
   "engineStrict": true,
   "engines": {
     "node": ">=8.9.4"
   },
   "dependencies": {
     "classnames": "^2.2.5",
@@ -33,17 +33,17 @@
     "redux": "^3.7.2"
   },
   "devDependencies": {
     "@sucrase/webpack-object-rest-spread-plugin": "^1.0.0",
     "babel-plugin-syntax-object-rest-spread": "^6.13.0",
     "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
     "babel-preset-react": "^6.24.1",
     "devtools-config": "^0.0.16",
-    "devtools-launchpad": "^0.0.145",
+    "devtools-launchpad": "^0.0.149",
     "devtools-license-check": "^0.7.0",
     "devtools-modules": "~1.1.0",
     "devtools-services": "^0.0.1",
     "enzyme": "^3.3.0",
     "enzyme-adapter-react-16": "^1.1.1",
     "enzyme-to-json": "^3.3.1",
     "eslint": "^5.0.0",
     "eslint-plugin-mozilla": "1.1.1",
--- a/devtools/client/debugger/new/packages/devtools-reps/src/object-inspector/components/ObjectInspector.js
+++ b/devtools/client/debugger/new/packages/devtools-reps/src/object-inspector/components/ObjectInspector.js
@@ -70,33 +70,36 @@ class ObjectInspector extends Component<
     this.cachedNodes = new Map();
 
     const self: any = this;
 
     self.getItemChildren = this.getItemChildren.bind(this);
     self.isNodeExpandable = this.isNodeExpandable.bind(this);
     self.setExpanded = this.setExpanded.bind(this);
     self.focusItem = this.focusItem.bind(this);
+    self.activateItem = this.activateItem.bind(this);
     self.getRoots = this.getRoots.bind(this);
     self.getNodeKey = this.getNodeKey.bind(this);
   }
 
   componentWillMount() {
     this.roots = this.props.roots;
     this.focusedItem = this.props.focusedItem;
+    this.activeItem = this.props.activeItem;
   }
 
   componentWillUpdate(nextProps) {
     this.removeOutdatedNodesFromCache(nextProps);
 
     if (this.roots !== nextProps.roots) {
       // Since the roots changed, we assume the properties did as well,
       // so we need to cleanup the component internal state.
       this.roots = nextProps.roots;
       this.focusedItem = nextProps.focusedItem;
+      this.activeItem = nextProps.activeItem;
       if (this.props.rootsChanged) {
         this.props.rootsChanged();
       }
       return;
     }
   }
 
   removeOutdatedNodesFromCache(nextProps) {
@@ -123,26 +126,28 @@ class ObjectInspector extends Component<
     // We should update if:
     // - there are new loaded properties
     // - OR there are new evaluations
     // - OR the expanded paths number changed, and all of them have properties
     //      loaded
     // - OR the expanded paths number did not changed, but old and new sets
     //      differ
     // - OR the focused node changed.
+    // - OR the active node changed.
     return (
       loadedProperties.size !== nextProps.loadedProperties.size ||
       evaluations.size !== nextProps.evaluations.size ||
       (expandedPaths.size !== nextProps.expandedPaths.size &&
         [...nextProps.expandedPaths].every(path =>
           nextProps.loadedProperties.has(path)
         )) ||
       (expandedPaths.size === nextProps.expandedPaths.size &&
         [...nextProps.expandedPaths].some(key => !expandedPaths.has(key))) ||
       this.focusedItem !== nextProps.focusedItem ||
+      this.activeItem !== nextProps.activeItem ||
       this.roots !== nextProps.roots
     );
   }
 
   componentWillUnmount() {
     this.props.closeObjectInspector();
   }
 
@@ -214,16 +219,29 @@ class ObjectInspector extends Component<
       this.forceUpdate();
 
       if (onFocus) {
         onFocus(item);
       }
     }
   }
 
+  activateItem(item: Node) {
+    const { focusable = true, onActivate } = this.props;
+
+    if (focusable && this.activeItem !== item) {
+      this.activeItem = item;
+      this.forceUpdate();
+
+      if (onActivate) {
+        onActivate(item);
+      }
+    }
+  }
+
   render() {
     const {
       autoExpandAll = true,
       autoExpandDepth = 1,
       focusable = true,
       disableWrap = false,
       expandedPaths,
       inline
@@ -237,25 +255,27 @@ class ObjectInspector extends Component<
       }),
 
       autoExpandAll,
       autoExpandDepth,
 
       isExpanded: item => expandedPaths && expandedPaths.has(item.path),
       isExpandable: this.isNodeExpandable,
       focused: this.focusedItem,
+      active: this.activeItem,
 
       getRoots: this.getRoots,
       getParent,
       getChildren: this.getItemChildren,
       getKey: this.getNodeKey,
 
       onExpand: item => this.setExpanded(item, true),
       onCollapse: item => this.setExpanded(item, false),
       onFocus: focusable ? this.focusItem : null,
+      onActivate: focusable ? this.activateItem : null,
 
       renderItem: (item, depth, focused, arrow, expanded) =>
         ObjectInspectorItem({
           ...this.props,
           item,
           depth,
           focused,
           arrow,
--- a/devtools/client/debugger/new/packages/devtools-reps/src/object-inspector/tests/component/__snapshots__/classnames.js.snap
+++ b/devtools/client/debugger/new/packages/devtools-reps/src/object-inspector/tests/component/__snapshots__/classnames.js.snap
@@ -13,16 +13,17 @@ exports[`ObjectInspector - classnames ha
   tabIndex="0"
 >
   <div
     aria-level={1}
     className="tree-node"
     data-expandable={false}
     id="root"
     onClick={[Function]}
+    onKeyDownCapture={null}
     role="treeitem"
   >
     <div
       className="node object-node"
       onClick={[Function]}
     >
       <span
         className="object-label"
@@ -57,16 +58,17 @@ exports[`ObjectInspector - classnames ha
   tabIndex="0"
 >
   <div
     aria-level={1}
     className="tree-node"
     data-expandable={false}
     id="root"
     onClick={[Function]}
+    onKeyDownCapture={null}
     role="treeitem"
   >
     <div
       className="node object-node"
       onClick={[Function]}
     >
       <span
         className="object-label"
@@ -101,16 +103,17 @@ exports[`ObjectInspector - classnames ha
   tabIndex="0"
 >
   <div
     aria-level={1}
     className="tree-node"
     data-expandable={false}
     id="root"
     onClick={[Function]}
+    onKeyDownCapture={null}
     role="treeitem"
   >
     <div
       className="node object-node"
       onClick={[Function]}
     >
       <span
         className="object-label"
--- a/devtools/client/debugger/new/packages/devtools-reps/src/object-inspector/tests/component/__snapshots__/window.js.snap
+++ b/devtools/client/debugger/new/packages/devtools-reps/src/object-inspector/tests/component/__snapshots__/window.js.snap
@@ -14,16 +14,17 @@ exports[`ObjectInspector - dimTopLevelWi
 >
   <div
     aria-expanded={false}
     aria-level={1}
     className="tree-node"
     data-expandable={true}
     id="Symbol(window)"
     onClick={[Function]}
+    onKeyDownCapture={null}
     role="treeitem"
   >
     <div
       className="node object-node"
       onClick={[Function]}
     >
       <button
         className="arrow"
@@ -68,16 +69,17 @@ exports[`ObjectInspector - dimTopLevelWi
 >
   <div
     aria-expanded={true}
     aria-level={1}
     className="tree-node focused"
     data-expandable={true}
     id="Symbol(root)"
     onClick={[Function]}
+    onKeyDownCapture={null}
     role="treeitem"
   >
     <div
       className="node object-node focused"
       onClick={[Function]}
     >
       <button
         className="arrow expanded"
@@ -91,16 +93,17 @@ exports[`ObjectInspector - dimTopLevelWi
   </div>
   <div
     aria-expanded={false}
     aria-level={2}
     className="tree-node"
     data-expandable={true}
     id="Symbol(window)"
     onClick={[Function]}
+    onKeyDownCapture={null}
     role="treeitem"
   >
     <span
       className="tree-indent"
     >

     </span>
     <div
@@ -149,16 +152,17 @@ exports[`ObjectInspector - dimTopLevelWi
 >
   <div
     aria-expanded={false}
     aria-level={1}
     className="tree-node"
     data-expandable={true}
     id="Symbol(window)"
     onClick={[Function]}
+    onKeyDownCapture={null}
     role="treeitem"
   >
     <div
       className="node object-node lessen"
       onClick={[Function]}
     >
       <button
         className="arrow"
@@ -203,16 +207,17 @@ exports[`ObjectInspector - dimTopLevelWi
 >
   <div
     aria-expanded={true}
     aria-level={1}
     className="tree-node focused"
     data-expandable={true}
     id="Symbol(window)"
     onClick={[Function]}
+    onKeyDownCapture={null}
     role="treeitem"
   >
     <div
       className="node object-node focused"
       onClick={[Function]}
     >
       <button
         className="arrow expanded"
@@ -240,16 +245,17 @@ exports[`ObjectInspector - dimTopLevelWi
     </div>
   </div>
   <div
     aria-level={2}
     className="tree-node"
     data-expandable={false}
     id="Symbol(window/<prototype>)"
     onClick={[Function]}
+    onKeyDownCapture={null}
     role="treeitem"
   >
     <span
       className="tree-indent"
     >

     </span>
     <div
--- a/devtools/client/debugger/new/packages/devtools-reps/src/object-inspector/types.js
+++ b/devtools/client/debugger/new/packages/devtools-reps/src/object-inspector/types.js
@@ -98,16 +98,17 @@ export type Props = {
   mode: Mode,
   roots: Array<Node>,
   disableWrap: boolean,
   dimTopLevelWindow: boolean,
   releaseActor: string => void,
   createObjectClient: CreateObjectClient,
   createLongStringClient: CreateLongStringClient,
   onFocus: ?(Node) => any,
+  onActivate: ?(Node) => any,
   onDoubleClick: ?(
     item: Node,
     options: {
       depth: number,
       focused: boolean,
       expanded: boolean
     }
   ) => any,
@@ -127,30 +128,32 @@ export type Props = {
       focused: boolean,
       expanded: boolean,
       setExpanded: (Node, boolean) => any
     }
   ) => any,
   actors: Set<string>,
   expandedPaths: Set<Path>,
   focusedItem: ?Node,
+  activeItem: ?Node,
   loadedProperties: LoadedProperties,
   evaluations: Evaluations,
   loading: Map<Path, Array<Promise<GripProperties>>>
 };
 
 export type ReduxAction = {
   type: string,
   data: {}
 };
 
 export type State = {
   actors: Set<string>,
   expandedPaths: Set<Path>,
   focusedItem: ?Node,
+  activeItem: ?Node,
   loadedProperties: LoadedProperties
 };
 
 export type Store = {
   dispatch: any => any,
   getState: () => State
 };
 
--- a/devtools/client/debugger/new/packages/devtools-reps/src/reps/grip-array.js
+++ b/devtools/client/debugger/new/packages/devtools-reps/src/reps/grip-array.js
@@ -220,17 +220,17 @@ function arrayIterator(props, grip, max)
   if (gripLength > itemsShown) {
     items.push(ellipsisElement);
   }
 
   return items;
 }
 
 function getEmptySlotsElement(number) {
-  // TODO: Use l10N - See https://github.com/devtools-html/reps/issues/141
+  // TODO: Use l10N - See https://github.com/firefox-devtools/reps/issues/141
   return `<${number} empty slot${number > 1 ? "s" : ""}>`;
 }
 
 function supportsObject(grip, noGrip = false) {
   if (noGrip === true || !isGrip(grip)) {
     return false;
   }
 
--- a/devtools/client/debugger/new/packages/devtools-reps/src/reps/reps.css
+++ b/devtools/client/debugger/new/packages/devtools-reps/src/reps/reps.css
@@ -246,57 +246,57 @@ button.open-inspector {
   mask: url("/images/open-inspector.svg") no-repeat;
   display: inline-block;
   vertical-align: top;
   height: 15px;
   width: 15px;
   margin: 0 4px;
   padding: 0;
   border: none;
-  background-color: var(--comment-node-color);
+  background-color: var(--theme-icon-color);
   cursor: pointer;
 }
 
 .objectBox-accessible:hover .open-accessibility-inspector,
 .objectBox-node:hover .open-inspector,
 .objectBox-textNode:hover .open-inspector,
 .open-accessibility-inspector:hover,
 .open-inspector:hover {
-  background-color: var(--theme-highlight-blue);
+  background-color: var(--theme-icon-checked-color);
 }
 
 /******************************************************************************/
 /* Jump to definition button */
 
 button.jump-definition {
   mask: url(/images/jump-definition.svg) no-repeat;
   display: inline-block;
-  background-color: var(--comment-node-color);
+  background-color: var(--theme-icon-color);
   height: 16px;
   margin-left: 0.25em;
   vertical-align: middle;
 }
 
 .jump-definition:hover {
-  background-color: var(--theme-highlight-blue);
+  background-color: var(--theme-icon-checked-color);
 }
 
 /******************************************************************************/
 /* Invoke getter button */
 
 button.invoke-getter {
   mask: url(/images/input.svg) no-repeat;
   display: inline-block;
-  background-color: var(--comment-node-color);
+  background-color: var(--theme-icon-color);
   height: 10px;
   vertical-align: middle;
   border:none;
 }
 
 .invoke-getter:hover {
-  background-color: var(--theme-highlight-blue);
+  background-color: var(--theme-icon-checked-color);
 }
 
 /******************************************************************************/
 /* "more…" ellipsis */
 .more-ellipsis {
   color: var(--comment-node-color);
 }
--- a/devtools/client/debugger/new/packages/devtools-source-map/package.json
+++ b/devtools/client/debugger/new/packages/devtools-source-map/package.json
@@ -1,18 +1,18 @@
 {
   "name": "devtools-source-map",
   "version": "0.16.0",
   "description": "DevTools utilities for working with source maps",
   "license": "MPL-2.0",
   "author": "Jason Laster <jlaster@mozilla.com>",
   "repository": "github:devtools-html/debugger.html",
-  "bugs": "https://github.com/devtools-html/debugger.html/issues",
+  "bugs": "https://github.com/firefox-devtools/debugger.html/issues",
   "homepage":
-    "https://github.com/devtools-html/debugger.html/tree/master/packages/source-maps#readme",
+    "https://github.com/firefox-devtools/debugger.html/tree/master/packages/source-maps#readme",
   "main": "src/index.js",
   "browser": {
     "./src/utils/wasmAsset.js": "./src/utils/wasmAssetBrowser.js"
   },
   "scripts": {
     "license-check": "devtools-license-check",
     "test": "jest --projects jest.config.js"
   },
--- a/devtools/client/debugger/new/packages/devtools-source-map/src/index.js
+++ b/devtools/client/debugger/new/packages/devtools-source-map/src/index.js
@@ -3,17 +3,17 @@
  * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
 
 // @flow
 
 const {
   workerUtils: { WorkerDispatcher }
 } = require("devtools-utils");
 
-import type { SourceLocation, Source, SourceId } from "debugger-html";
+import type { SourceLocation, Source, SourceId } from "../../../src/types";
 import type { SourceMapConsumer } from "source-map";
 import type { locationOptions } from "./source-map";
 
 export const dispatcher = new WorkerDispatcher();
 
 const _getGeneratedRanges = dispatcher.task("getGeneratedRanges", {
   queue: true
 });
--- a/devtools/client/debugger/new/src/actions/README.md
+++ b/devtools/client/debugger/new/src/actions/README.md
@@ -17,10 +17,10 @@ If you just want to cancel subsequent ca
 state in the store. [ex][state]
 
 The advantage of adding the pending state to the store is that we can use that
 in the UI:
 
 * disable/hide the pretty print button
 * show a progress ui
 
-[req]: https://github.com/devtools-html/debugger.html/blob/master/src/actions/sources/loadSourceText.js
-[state]: https://github.com/devtools-html/debugger.html/blob/master/src/reducers/sources.js
+[req]: https://github.com/firefox-devtools/debugger.html/blob/master/src/actions/sources/loadSourceText.js
+[state]: https://github.com/firefox-devtools/debugger.html/blob/master/src/reducers/sources.js
--- a/devtools/client/debugger/new/src/actions/ast.js
+++ b/devtools/client/debugger/new/src/actions/ast.js
@@ -13,18 +13,16 @@ import {
 } from "../selectors";
 
 import { mapFrames } from "./pause";
 import { updateTab } from "./tabs";
 
 import { PROMISE } from "./utils/middleware/promise";
 
 import { setInScopeLines } from "./ast/setInScopeLines";
-import { setPausePoints } from "./ast/setPausePoints";
-export { setPausePoints };
 
 import * as parser from "../workers/parser";
 
 import { isLoaded } from "../utils/source";
 
 import type { SourceId } from "../types";
 import type { ThunkArgs, Action } from "./types";
 
@@ -65,17 +63,16 @@ export function setSymbols(sourceId: Sou
       sourceId,
       [PROMISE]: parser.getSymbols(sourceId)
     });
 
     if (isPaused(getState())) {
       await dispatch(mapFrames());
     }
 
-    await dispatch(setPausePoints(sourceId));
     await dispatch(setSourceMetaData(sourceId));
   };
 }
 
 export function setOutOfScopeLocations() {
   return async ({ dispatch, getState }: ThunkArgs) => {
     const location = getSelectedLocation(getState());
     if (!location) {
--- a/devtools/client/debugger/new/src/actions/ast/moz.build
+++ b/devtools/client/debugger/new/src/actions/ast/moz.build
@@ -4,10 +4,9 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 DIRS += [
 
 ]
 
 DebuggerModules(
     'setInScopeLines.js',
-    'setPausePoints.js',
 )
--- a/devtools/client/debugger/new/src/actions/ast/setPausePoints.js
+++ b/devtools/client/debugger/new/src/actions/ast/setPausePoints.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/>. */
 
 // @flow
 
-import { getSourceFromId, getSourceActors } from "../../selectors";
+import { getSourceFromId } from "../../selectors";
 import * as parser from "../../workers/parser";
-import { isGenerated } from "../../utils/source";
 import { convertToList } from "../../utils/pause/pausePoints";
 import { features } from "../../utils/prefs";
 import { getGeneratedLocation } from "../../utils/source-maps";
 
 import type { SourceId } from "../../types";
 import type { ThunkArgs, Action } from "../types";
 
 async function mapLocations(pausePoints, state, source, sourceMaps) {
--- a/devtools/client/debugger/new/src/actions/breakpoints/breakpointPositions.js
+++ b/devtools/client/debugger/new/src/actions/breakpoints/breakpointPositions.js
@@ -1,37 +1,69 @@
 /* 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/>. */
 
 // @flow
 
+import { isOriginalId, originalToGeneratedId } from "devtools-source-map";
+
 import {
-  getSourceActors,
-  getBreakpointPositionsForLine
+  getSourceFromId,
+  getBreakpointPositionsForSource
 } from "../../selectors";
 
-import { makeSourceActorLocation } from "../../utils/breakpoint";
-
 import type { SourceLocation } from "../../types";
 import type { ThunkArgs } from "../../actions/types";
+import { getOriginalLocation } from "../../utils/source-maps";
+
+async function mapLocations(generatedLocations, state, source, sourceMaps) {
+  return Promise.all(
+    generatedLocations.map(async generatedLocation => {
+      const location = await getOriginalLocation(
+        generatedLocation,
+        source,
+        sourceMaps
+      );
+
+      return { location, generatedLocation };
+    })
+  );
+}
+
+function convertToList(results, sourceId) {
+  const positions = [];
+
+  for (const line in results) {
+    for (const column of results[line]) {
+      positions.push({ line: Number(line), column: column, sourceId });
+    }
+  }
+
+  return positions;
+}
 
 export function setBreakpointPositions(location: SourceLocation) {
-  return async ({ getState, dispatch, client }: ThunkArgs) => {
-    if (
-      getBreakpointPositionsForLine(
-        getState(),
-        location.sourceId,
-        location.line
-      )
-    ) {
+  return async ({ getState, dispatch, client, sourceMaps }: ThunkArgs) => {
+    let sourceId = location.sourceId;
+    if (getBreakpointPositionsForSource(getState(), sourceId)) {
       return;
     }
 
-    const sourceActors = getSourceActors(getState(), location.sourceId);
-    const sourceActor = sourceActors[0];
+    let source = getSourceFromId(getState(), sourceId);
 
-    const sourceActorLocation = makeSourceActorLocation(sourceActor, location);
-    const positions = await client.getBreakpointPositions(sourceActorLocation);
+    let range;
+    if (isOriginalId(sourceId)) {
+      range = await sourceMaps.getFileGeneratedRange(source);
+      sourceId = originalToGeneratedId(sourceId);
+      source = getSourceFromId(getState(), sourceId);
+    }
 
+    const results = await client.getBreakpointPositions(
+      source.actors[0],
+      range
+    );
+
+    let positions = convertToList(results, sourceId);
+    positions = await mapLocations(positions, getState(), source, sourceMaps);
     return dispatch({ type: "ADD_BREAKPOINT_POSITIONS", positions, location });
   };
 }
--- a/devtools/client/debugger/new/src/actions/breakpoints/index.js
+++ b/devtools/client/debugger/new/src/actions/breakpoints/index.js
@@ -294,17 +294,16 @@ export function setBreakpointOptions(
     if (bp.disabled) {
       await dispatch(enableBreakpoint(bp));
     }
 
     const breakpointLocation = makeBreakpointLocation(
       getState(),
       bp.generatedLocation
     );
-
     await client.setBreakpoint(breakpointLocation, options);
 
     const newBreakpoint = { ...bp, disabled: false, options };
 
     assertBreakpoint(newBreakpoint);
 
     return dispatch(
       ({
--- a/devtools/client/debugger/new/src/actions/breakpoints/syncBreakpoint.js
+++ b/devtools/client/debugger/new/src/actions/breakpoints/syncBreakpoint.js
@@ -30,16 +30,27 @@ import type {
   Breakpoint
 } from "../../types";
 
 type BreakpointSyncData = {
   previousLocation: SourceLocation,
   breakpoint: ?Breakpoint
 };
 
+async function isPossiblePosition(location, dispatch) {
+  if (features.columnBreakpoints && location.column != undefined) {
+    const { positions } = await dispatch(setBreakpointPositions(location));
+    if (!positions.some(({ generatedLocation }) => generatedLocation.column)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
 async function makeScopedLocation(
   { name, offset, index }: ASTLocation,
   location: SourceLocation,
   source
 ) {
   const scope = await findScopeByName(source, name, index);
   // fallback onto the location line, if the scope is not found
   // note: we may at some point want to delete the breakpoint if the scope
@@ -131,25 +142,20 @@ export async function syncBreakpointProm
     return null;
   }
 
   const breakpointLocation = makeBreakpointLocation(
     getState(),
     generatedLocation
   );
 
-  let possiblePosition = true;
-  if (features.columnBreakpoints && generatedLocation.column != undefined) {
-    const { positions } = await dispatch(
-      setBreakpointPositions(generatedLocation)
-    );
-    if (!positions.includes(generatedLocation.column)) {
-      possiblePosition = false;
-    }
-  }
+  const possiblePosition = await isPossiblePosition(
+    generatedLocation,
+    dispatch
+  );
 
   /** ******* CASE 1: No server change ***********/
   // early return if breakpoint is disabled or we are in the sameLocation
   if (possiblePosition && (pendingBreakpoint.disabled || isSameLocation)) {
     // Make sure the breakpoint is installed on all source actors.
     if (!pendingBreakpoint.disabled) {
       await client.setBreakpoint(breakpointLocation, pendingBreakpoint.options);
     }
--- a/devtools/client/debugger/new/src/actions/breakpoints/tests/__snapshots__/breakpoints.spec.js.snap
+++ b/devtools/client/debugger/new/src/actions/breakpoints/tests/__snapshots__/breakpoints.spec.js.snap
@@ -32,24 +32,32 @@ Array [
           "hidden": false,
           "logValue": null,
         },
         "originalText": "return a",
         "text": "return a",
       },
     ],
     "source": Object {
+      "actors": Array [
+        Object {
+          "actor": "a-actor",
+          "source": "a",
+          "thread": "FakeThread",
+        },
+      ],
       "contentType": "text/javascript",
       "error": undefined,
       "id": "a",
       "isBlackBoxed": false,
       "isExtension": false,
       "isPrettyPrinted": false,
       "isWasm": false,
       "loadedState": "loaded",
+      "relativeUrl": "/examples/a",
       "sourceMapURL": undefined,
       "text": "function a() {
   return a 
 }",
       "url": "http://localhost:8000/examples/a",
     },
   },
 ]
@@ -124,24 +132,32 @@ Array [
           "hidden": false,
           "logValue": null,
         },
         "originalText": "",
         "text": "",
       },
     ],
     "source": Object {
+      "actors": Array [
+        Object {
+          "actor": "a-actor",
+          "source": "a",
+          "thread": "FakeThread",
+        },
+      ],
       "contentType": "text/javascript",
       "error": undefined,
       "id": "a",
       "isBlackBoxed": false,
       "isExtension": false,
       "isPrettyPrinted": false,
       "isWasm": false,
       "loadedState": "loaded",
+      "relativeUrl": "/examples/a",
       "sourceMapURL": undefined,
       "text": "function a() {
   return a 
 }",
       "url": "http://localhost:8000/examples/a",
     },
   },
 ]
--- a/devtools/client/debugger/new/src/actions/breakpoints/tests/breakpoints.spec.js
+++ b/devtools/client/debugger/new/src/actions/breakpoints/tests/breakpoints.spec.js
@@ -18,19 +18,19 @@ describe("breakpoints", () => {
   it("should add a breakpoint", async () => {
     const { dispatch, getState } = createStore(simpleMockThreadClient);
     const loc1 = {
       sourceId: "a",
       line: 2,
       sourceUrl: "http://localhost:8000/examples/a"
     };
 
-    const csr = makeSource("a");
-    await dispatch(actions.newSource(csr));
-    await dispatch(actions.loadSourceText(csr.source));
+    const source = makeSource("a");
+    await dispatch(actions.newSource(source));
+    await dispatch(actions.loadSourceText(source));
     await dispatch(actions.addBreakpoint(loc1));
 
     expect(selectors.getBreakpointCount(getState())).toEqual(1);
     const bp = selectors.getBreakpoint(getState(), loc1);
     expect(bp && bp.location).toEqual(loc1);
     expect(getTelemetryEvents("add_breakpoint")).toHaveLength(1);
 
     const bpSources = selectors.getBreakpointSources(getState());
@@ -39,37 +39,37 @@ describe("breakpoints", () => {
 
   it("should not show a breakpoint that does not have text", async () => {
     const { dispatch, getState } = createStore(simpleMockThreadClient);
     const loc1 = {
       sourceId: "a",
       line: 5,
       sourceUrl: "http://localhost:8000/examples/a"
     };
-    const csr = makeSource("a");
-    await dispatch(actions.newSource(csr));
-    await dispatch(actions.loadSourceText(csr.source));
+    const source = makeSource("a");
+    await dispatch(actions.newSource(source));
+    await dispatch(actions.loadSourceText(source));
     await dispatch(actions.addBreakpoint(loc1));
 
     expect(selectors.getBreakpointCount(getState())).toEqual(1);
     const bp = selectors.getBreakpoint(getState(), loc1);
     expect(bp && bp.location).toEqual(loc1);
     expect(selectors.getBreakpointSources(getState())).toMatchSnapshot();
   });
 
   it("should show a disabled breakpoint that does not have text", async () => {
     const { dispatch, getState } = createStore(simpleMockThreadClient);
     const loc1 = {
       sourceId: "a",
       line: 5,
       sourceUrl: "http://localhost:8000/examples/a"
     };
-    const csr = makeSource("a");
-    await dispatch(actions.newSource(csr));
-    await dispatch(actions.loadSourceText(csr.source));
+    const source = makeSource("a");
+    await dispatch(actions.newSource(source));
+    await dispatch(actions.loadSourceText(source));
     const breakpoint = await dispatch(actions.addBreakpoint(loc1));
     await dispatch(actions.disableBreakpoint(breakpoint));
 
     expect(selectors.getBreakpointCount(getState())).toEqual(1);
     const bp = selectors.getBreakpoint(getState(), loc1);
     expect(bp && bp.location).toEqual(loc1);
     expect(selectors.getBreakpointSources(getState())).toMatchSnapshot();
   });
@@ -77,19 +77,19 @@ describe("breakpoints", () => {
   it("should not re-add a breakpoint", async () => {
     const { dispatch, getState } = createStore(simpleMockThreadClient);
     const loc1 = {
       sourceId: "a",
       line: 5,
       sourceUrl: "http://localhost:8000/examples/a"
     };
 
-    const csr = makeSource("a");
-    await dispatch(actions.newSource(csr));
-    await dispatch(actions.loadSourceText(csr.source));
+    const source = makeSource("a");
+    await dispatch(actions.newSource(source));
+    await dispatch(actions.loadSourceText(source));
 
     await dispatch(actions.addBreakpoint(loc1));
     expect(selectors.getBreakpointCount(getState())).toEqual(1);
     const bp = selectors.getBreakpoint(getState(), loc1);
     expect(bp && bp.location).toEqual(loc1);
 
     await dispatch(actions.addBreakpoint(loc1));
     expect(selectors.getBreakpointCount(getState())).toEqual(1);
@@ -105,23 +105,23 @@ describe("breakpoints", () => {
     };
 
     const loc2 = {
       sourceId: "b",
       line: 6,
       sourceUrl: "http://localhost:8000/examples/b"
     };
 
-    const aCSR = makeSource("a");
-    await dispatch(actions.newSource(aCSR));
-    await dispatch(actions.loadSourceText(aCSR.source));
+    const aSource = makeSource("a");
+    await dispatch(actions.newSource(aSource));
+    await dispatch(actions.loadSourceText(aSource));
 
-    const bCSR = makeSource("b");
-    await dispatch(actions.newSource(bCSR));
-    await dispatch(actions.loadSourceText(bCSR.source));
+    const bSource = makeSource("b");
+    await dispatch(actions.newSource(bSource));
+    await dispatch(actions.loadSourceText(bSource));
 
     await dispatch(actions.addBreakpoint(loc1));
     await dispatch(actions.addBreakpoint(loc2));
 
     const bp = selectors.getBreakpoint(getState(), loc1);
     if (!bp) {
       throw new Error("no bp");
     }
@@ -140,23 +140,23 @@ describe("breakpoints", () => {
     };
 
     const loc2 = {
       sourceId: "b",
       line: 6,
       sourceUrl: "http://localhost:8000/examples/b"
     };
 
-    const aCSR = makeSource("a");
-    await dispatch(actions.newSource(aCSR));
-    await dispatch(actions.loadSourceText(aCSR.source));
+    const aSource = makeSource("a");
+    await dispatch(actions.newSource(aSource));
+    await dispatch(actions.loadSourceText(aSource));
 
-    const bCSR = makeSource("b");
-    await dispatch(actions.newSource(bCSR));
-    await dispatch(actions.loadSourceText(bCSR.source));
+    const bSource = makeSource("b");
+    await dispatch(actions.newSource(bSource));
+    await dispatch(actions.loadSourceText(bSource));
 
     const breakpoint = await dispatch(actions.addBreakpoint(loc1));
     await dispatch(actions.addBreakpoint(loc2));
 
     await dispatch(actions.disableBreakpoint(breakpoint));
 
     const bp = selectors.getBreakpoint(getState(), loc1);
     expect(bp && bp.disabled).toBe(true);
@@ -165,19 +165,19 @@ describe("breakpoints", () => {
   it("should enable breakpoint", async () => {
     const { dispatch, getState } = createStore(simpleMockThreadClient);
     const loc = {
       sourceId: "a",
       line: 5,
       sourceUrl: "http://localhost:8000/examples/a"
     };
 
-    const aCSR = makeSource("a");
-    await dispatch(actions.newSource(aCSR));
-    await dispatch(actions.loadSourceText(aCSR.source));
+    const aSource = makeSource("a");
+    await dispatch(actions.newSource(aSource));
+    await dispatch(actions.loadSourceText(aSource));
 
     const breakpoint = await dispatch(actions.addBreakpoint(loc));
     await dispatch(actions.disableBreakpoint(breakpoint));
 
     let bp = selectors.getBreakpoint(getState(), loc);
     expect(bp && bp.disabled).toBe(true);
 
     await dispatch(actions.enableBreakpoint(breakpoint));
@@ -196,23 +196,23 @@ describe("breakpoints", () => {
     };
 
     const loc2 = {
       sourceId: "b",
       line: 6,
       sourceUrl: "http://localhost:8000/examples/b"
     };
 
-    const aCSR = makeSource("a");
-    await dispatch(actions.newSource(aCSR));
-    await dispatch(actions.loadSourceText(aCSR.source));
+    const aSource = makeSource("a");
+    await dispatch(actions.newSource(aSource));
+    await dispatch(actions.loadSourceText(aSource));
 
-    const bCSR = makeSource("b");
-    await dispatch(actions.newSource(bCSR));
-    await dispatch(actions.loadSourceText(bCSR.source));
+    const bSource = makeSource("b");
+    await dispatch(actions.newSource(bSource));
+    await dispatch(actions.loadSourceText(bSource));
 
     await dispatch(actions.addBreakpoint(loc1));
     await dispatch(actions.addBreakpoint(loc2));
 
     await dispatch(actions.toggleAllBreakpoints(true));
 
     let bp1 = selectors.getBreakpoint(getState(), loc1);
     let bp2 = selectors.getBreakpoint(getState(), loc2);
@@ -228,19 +228,19 @@ describe("breakpoints", () => {
   });
 
   it("should toggle a breakpoint at a location", async () => {
     const location = { sourceId: "foo1", line: 5 };
     const getBp = () => selectors.getBreakpoint(getState(), location);
 
     const { dispatch, getState } = createStore(simpleMockThreadClient);
 
-    const csr = makeSource("foo1");
-    await dispatch(actions.newSource(csr));
-    await dispatch(actions.loadSourceText(csr.source));
+    const source = makeSource("foo1");
+    await dispatch(actions.newSource(source));
+    await dispatch(actions.loadSourceText(source));
 
     await dispatch(actions.selectLocation({ sourceId: "foo1", line: 1 }));
 
     await dispatch(actions.toggleBreakpointAtLine(5));
     const bp = getBp();
     expect(bp && !bp.disabled).toBe(true);
 
     await dispatch(actions.toggleBreakpointAtLine(5));
@@ -248,19 +248,19 @@ describe("breakpoints", () => {
   });
 
   it("should disable/enable a breakpoint at a location", async () => {
     const location = { sourceId: "foo1", line: 5 };
     const getBp = () => selectors.getBreakpoint(getState(), location);
 
     const { dispatch, getState } = createStore(simpleMockThreadClient);
 
-    const csr = makeSource("foo1");
-    await dispatch(actions.newSource(csr));
-    await dispatch(actions.loadSourceText(csr.source));
+    const source = makeSource("foo1");
+    await dispatch(actions.newSource(source));
+    await dispatch(actions.loadSourceText(source));
 
     await dispatch(actions.selectLocation({ sourceId: "foo1", line: 1 }));
 
     await dispatch(actions.toggleBreakpointAtLine(5));
     let bp = getBp();
     expect(bp && !bp.disabled).toBe(true);
     bp = getBp();
     if (!bp) {
@@ -275,19 +275,19 @@ describe("breakpoints", () => {
     const { dispatch, getState } = createStore(simpleMockThreadClient);
 
     const loc = {
       sourceId: "a",
       line: 5,
       sourceUrl: "http://localhost:8000/examples/a"
     };
 
-    const csr = makeSource("a");
-    await dispatch(actions.newSource(csr));
-    await dispatch(actions.loadSourceText(csr.source));
+    const source = makeSource("a");
+    await dispatch(actions.newSource(source));
+    await dispatch(actions.loadSourceText(source));
 
     await dispatch(actions.addBreakpoint(loc));
 
     let bp = selectors.getBreakpoint(getState(), loc);
     expect(bp && bp.options.condition).toBe(null);
 
     await dispatch(
       actions.setBreakpointOptions(loc, {
@@ -333,19 +333,19 @@ describe("breakpoints", () => {
     const { dispatch, getState } = createStore(simpleMockThreadClient);
 
     const loc = {
       sourceId: "a.js",
       line: 1,
       sourceUrl: "http://localhost:8000/examples/a.js"
     };
 
-    const csr = makeSource("a.js");
-    await dispatch(actions.newSource(csr));
-    await dispatch(actions.loadSourceText(csr.source));
+    const source = makeSource("a.js");
+    await dispatch(actions.newSource(source));
+    await dispatch(actions.loadSourceText(source));
 
     await dispatch(actions.addBreakpoint(loc));
     await dispatch(actions.togglePrettyPrint("a.js"));
 
     const breakpoint = selectors.getBreakpointsList(getState())[0];
 
     expect(
       breakpoint.location.sourceUrl &&
--- a/devtools/client/debugger/new/src/actions/breakpoints/tests/syncing.spec.js
+++ b/devtools/client/debugger/new/src/actions/breakpoints/tests/syncing.spec.js
@@ -132,17 +132,17 @@ describe("loading the debugger", () => {
 
     expect(selectors.getBreakpointCount(getState())).toEqual(0);
     // manually sync
     const update = await syncBreakpointPromise(
       getState,
       threadClient,
       sourceMaps,
       dispatch,
-      reloadedSource.source.id,
+      reloadedSource.id,
       pendingBreakpoint()
     );
 
     expect(threadClient.removeBreakpoint.mock.calls).toHaveLength(0);
     expect(update).toMatchSnapshot();
   });
 
   it("loads the initial breakpoint state with a changed file", async () => {
@@ -163,17 +163,17 @@ describe("loading the debugger", () => {
 
     expect(selectors.getBreakpointCount(getState())).toEqual(0);
     // manually sync
     const update = await syncBreakpointPromise(
       getState,
       threadClient,
       sourceMaps,
       dispatch,
-      reloadedSource.source.id,
+      reloadedSource.id,
       pendingBreakpoint()
     );
 
     expect(threadClient.removeBreakpoint.mock.calls).toHaveLength(0);
     expect(update && update.breakpoint && update.breakpoint.location.line).toBe(
       location.line + generated
     );
     expect(update).toMatchSnapshot();
@@ -208,17 +208,17 @@ describe("reloading debuggee", () => {
     await dispatch(actions.addBreakpoint(loc1));
 
     // manually sync
     const update = await syncBreakpointPromise(
       getState,
       threadClient,
       sourceMaps,
       dispatch,
-      reloadedSource.source.id,
+      reloadedSource.id,
       pendingBreakpoint({ location: loc1 })
     );
     expect(threadClient.removeBreakpoint.mock.calls).toHaveLength(0);
     expect(update).toMatchSnapshot();
   });
 
   it("updates a corresponding breakpoint for a changed source", async () => {
     /*
@@ -252,17 +252,17 @@ describe("reloading debuggee", () => {
     await dispatch(actions.newSource(generatedSource));
 
     // manually sync
     const update = await syncBreakpointPromise(
       getState,
       threadClient,
       sourceMaps,
       dispatch,
-      reloadedSource.source.id,
+      reloadedSource.id,
       pendingBreakpoint()
     );
     expect(threadClient.removeBreakpoint.mock.calls).toHaveLength(1);
     expect(findScopeByName).toHaveBeenCalled();
     expect(update).toMatchSnapshot();
   });
 
   it("syncs with changed source and an existing disabled BP", async () => {
@@ -274,30 +274,30 @@ describe("reloading debuggee", () => {
 
     const reloadedSource = makeSource("magic.js");
     await dispatch(actions.newSource(reloadedSource));
 
     const generatedSource = makeSource("gen.js");
     await dispatch(actions.newSource(generatedSource));
 
     const location = {
-      sourceId: reloadedSource.source.id,
+      sourceId: reloadedSource.id,
       line: 3,
       column: undefined
     };
 
     const breakpoint = await dispatch(actions.addBreakpoint(location));
     await dispatch(actions.disableBreakpoint(breakpoint));
 
     (getGeneratedLocation: any).mockImplementationOnce(() =>
       newGeneratedLocation(1)
     );
 
     await dispatch(
       actions.syncBreakpoint(
-        reloadedSource.source.id,
+        reloadedSource.id,
         pendingBreakpoint({ disabled: true })
       )
     );
 
     expect(selectors.getPendingBreakpoints(getState())).toMatchSnapshot();
   });
 });
--- a/devtools/client/debugger/new/src/actions/pause/paused.js
+++ b/devtools/client/debugger/new/src/actions/pause/paused.js
@@ -2,70 +2,42 @@
  * 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/>. */
 
 // @flow
 import {
   getHiddenBreakpoint,
   isEvaluatingExpression,
   getSelectedFrame,
-  getSources,
-  getLastCommand,
   wasStepping
 } from "../../selectors";
 
 import { mapFrames } from ".";
 import { removeBreakpoint } from "../breakpoints";
 import { evaluateExpressions } from "../expressions";
 import { selectLocation } from "../sources";
-import { loadSourceText } from "../sources/loadSourceText";
 import { togglePaneCollapse } from "../ui";
-import { command } from "./commands";
-import { shouldStep } from "../../utils/pause";
-
-import { updateFrameLocation } from "./mapFrames";
 
 import { fetchScopes } from "./fetchScopes";
 
-import type { Pause, Frame } from "../../types";
+import type { Pause } from "../../types";
 import type { ThunkArgs } from "../types";
 
-async function getOriginalSourceForFrame(state, frame: Frame) {
-  return getSources(state)[frame.location.sourceId];
-}
 /**
  * Debugger has just paused
  *
  * @param {object} pauseInfo
  * @memberof actions/pause
  * @static
  */
 export function paused(pauseInfo: Pause) {
   return async function({ dispatch, getState, client, sourceMaps }: ThunkArgs) {
     const { thread, frames, why, loadedObjects } = pauseInfo;
     const topFrame = frames.length > 0 ? frames[0] : null;
 
-    // NOTE: do not step when leaving a frame or paused at a debugger statement
-    if (topFrame && !why.frameFinished && why.type == "resumeLimit") {
-      const mappedFrame = await updateFrameLocation(topFrame, sourceMaps);
-      const source = await getOriginalSourceForFrame(getState(), mappedFrame);
-
-      // Ensure that the original file has loaded if there is one.
-      await dispatch(loadSourceText(source));
-
-      if (shouldStep(mappedFrame, getState(), sourceMaps)) {
-        // When stepping past a location we shouldn't pause at according to the
-        // source map, make sure we continue stepping in the same direction we
-        // were going previously.
-        const rewind = getLastCommand(getState(), thread) == "reverseStepOver";
-        dispatch(command(rewind ? "reverseStepOver" : "stepOver"));
-        return;
-      }
-    }
-
     dispatch({
       type: "PAUSED",
       thread,
       why,
       frames,
       selectedFrameId: topFrame ? topFrame.id : undefined,
       loadedObjects: loadedObjects || []
     });
--- a/devtools/client/debugger/new/src/actions/pause/tests/pause.spec.js
+++ b/devtools/client/debugger/new/src/actions/pause/tests/pause.spec.js
@@ -27,17 +27,16 @@ const mockThreadClient = {
       stepInResolve = _resolve;
     }),
   stepOver: () => new Promise(_resolve => _resolve),
   evaluate: async () => {},
   evaluateInFrame: async () => {},
   evaluateExpressions: async () => {},
 
   getFrameScopes: async frame => frame.scope,
-  setPausePoints: async () => {},
   setBreakpoint: () => new Promise(_resolve => {}),
   sourceContents: ({ source }) => {
     return new Promise((resolve, reject) => {
       switch (source) {
         case "foo1":
           return resolve({
             source: "function foo1() {\n  return 5;\n}",
             contentType: "text/javascript"
@@ -154,19 +153,19 @@ describe("pause", () => {
       const store = createStore(mockThreadClient);
       const { dispatch } = store;
       const mockPauseInfo = createPauseInfo({
         sourceId: "await",
         line: 2,
         column: 0
       });
 
-      const csr = makeSource("await");
-      await dispatch(actions.newSource(csr));
-      await dispatch(actions.loadSourceText(csr.source));
+      const source = makeSource("await");
+      await dispatch(actions.newSource(source));
+      await dispatch(actions.loadSourceText(source));
 
       await dispatch(actions.paused(mockPauseInfo));
       const getNextStepSpy = jest.spyOn(parser, "getNextStep");
       dispatch(actions.stepOver());
       expect(getNextStepSpy).toBeCalled();
       getNextStepSpy.mockRestore();
     });
 
@@ -174,19 +173,19 @@ describe("pause", () => {
       const store = createStore(mockThreadClient);
       const { dispatch } = store;
       const mockPauseInfo = createPauseInfo({
         sourceId: "await",
         line: 2,
         column: 6
       });
 
-      const csr = makeSource("await");
-      await dispatch(actions.newSource(csr));
-      await dispatch(actions.loadSourceText(csr.source));
+      const source = makeSource("await");
+      await dispatch(actions.newSource(source));
+      await dispatch(actions.loadSourceText(source));
 
       await dispatch(actions.paused(mockPauseInfo));
       const getNextStepSpy = jest.spyOn(parser, "getNextStep");
       dispatch(actions.stepOver());
       expect(getNextStepSpy).toBeCalled();
       getNextStepSpy.mockRestore();
     });
 
@@ -200,20 +199,20 @@ describe("pause", () => {
       const store = createStore(mockThreadClient, {});
       const { dispatch, getState } = store;
       const mockPauseInfo = createPauseInfo(generatedLocation, {
         scope: {
           bindings: { variables: { b: {} }, arguments: [{ a: {} }] }
         }
       });
 
-      const csr = makeSource("foo");
-      await dispatch(actions.newSource(csr));
+      const source = makeSource("foo");
+      await dispatch(actions.newSource(source));
       await dispatch(actions.newSource(makeOriginalSource("foo")));
-      await dispatch(actions.loadSourceText(csr.source));
+      await dispatch(actions.loadSourceText(source));
 
       await dispatch(actions.paused(mockPauseInfo));
       expect(selectors.getFrames(getState())).toEqual([
         {
           generatedLocation: { column: 0, line: 1, sourceId: "foo" },
           id: mockFrameId,
           location: { column: 0, line: 1, sourceId: "foo" },
           scope: {
@@ -262,22 +261,22 @@ describe("pause", () => {
         }),
         getGeneratedLocation: async location => location
       };
 
       const store = createStore(mockThreadClient, {}, sourceMapsMock);
       const { dispatch, getState } = store;
       const mockPauseInfo = createPauseInfo(generatedLocation);
 
-      const fooCSR = makeSource("foo");
-      const fooOriginalCSR = makeSource("foo-original");
-      await dispatch(actions.newSource(fooCSR));
-      await dispatch(actions.newSource(fooOriginalCSR));
-      await dispatch(actions.loadSourceText(fooCSR.source));
-      await dispatch(actions.loadSourceText(fooOriginalCSR.source));
+      const fooSource = makeSource("foo");
+      const fooOriginalSource = makeSource("foo-original");
+      await dispatch(actions.newSource(fooSource));
+      await dispatch(actions.newSource(fooOriginalSource));
+      await dispatch(actions.loadSourceText(fooSource));
+      await dispatch(actions.loadSourceText(fooOriginalSource));
       await dispatch(actions.setSymbols("foo-original"));
 
       await dispatch(actions.paused(mockPauseInfo));
       expect(selectors.getFrames(getState())).toEqual([
         {
           generatedLocation: { column: 0, line: 1, sourceId: "foo" },
           id: mockFrameId,
           location: { column: 0, line: 3, sourceId: "foo-original" },
@@ -323,23 +322,23 @@ describe("pause", () => {
           contentType: "text/rust"
         })
       };
 
       const store = createStore(mockThreadClient, {}, sourceMapsMock);
       const { dispatch, getState } = store;
       const mockPauseInfo = createPauseInfo(generatedLocation);
 
-      const csr = makeSource("foo-wasm", { isWasm: true });
-      const originalCSR = makeOriginalSource("foo-wasm");
+      const source = makeSource("foo-wasm", { isWasm: true });
+      const originalSource = makeOriginalSource("foo-wasm");
 
-      await dispatch(actions.newSource(csr));
-      await dispatch(actions.newSource(originalCSR));
-      await dispatch(actions.loadSourceText(csr.source));
-      await dispatch(actions.loadSourceText(originalCSR.source));
+      await dispatch(actions.newSource(source));
+      await dispatch(actions.newSource(originalSource));
+      await dispatch(actions.loadSourceText(source));
+      await dispatch(actions.loadSourceText(originalSource));
 
       await dispatch(actions.paused(mockPauseInfo));
       expect(selectors.getFrames(getState())).toEqual([
         {
           displayName: "fooBar",
           generatedLocation: { column: 0, line: 1, sourceId: "foo-wasm" },
           id: mockFrameId,
           isOriginal: true,
--- a/devtools/client/debugger/new/src/actions/sources/blackbox.js
+++ b/devtools/client/debugger/new/src/actions/sources/blackbox.js
@@ -7,26 +7,26 @@
 /**
  * Redux actions for the sources state
  * @module actions/sources
  */
 
 import { isOriginalId, originalToGeneratedId } from "devtools-source-map";
 import { recordEvent } from "../../utils/telemetry";
 import { features } from "../../utils/prefs";
-import { getSourceActors } from "../../selectors";
+import { getSourceFromId } from "../../selectors";
 
 import { PROMISE } from "../utils/middleware/promise";
 
 import type { Source } from "../../types";
 import type { ThunkArgs } from "../types";
 
 async function blackboxActors(state, client, sourceId, isBlackBoxed, range?) {
-  const sourceActors = getSourceActors(state, sourceId);
-  for (const sourceActor of sourceActors) {
+  const source = getSourceFromId(state, sourceId);
+  for (const sourceActor of source.actors) {
     await client.blackBox(sourceActor, isBlackBoxed, range);
   }
   return { isBlackBoxed: !isBlackBoxed };
 }
 
 export function toggleBlackBox(source: Source) {
   return async ({ dispatch, getState, client, sourceMaps }: ThunkArgs) => {
     const { isBlackBoxed } = source;
--- a/devtools/client/debugger/new/src/actions/sources/loadSourceText.js
+++ b/devtools/client/debugger/new/src/actions/sources/loadSourceText.js
@@ -1,51 +1,45 @@
 /* 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/>. */
 
 // @flow
 
 import { PROMISE } from "../utils/middleware/promise";
-import {
-  getGeneratedSource,
-  getSource,
-  getSourceActors
-} from "../../selectors";
+import { getGeneratedSource, getSource } from "../../selectors";
 import * as parser from "../../workers/parser";
 import { isLoaded, isOriginal } from "../../utils/source";
 import { Telemetry } from "devtools-modules";
 
 import defer from "../../utils/defer";
 import type { ThunkArgs } from "../types";
 
 import type { Source } from "../../types";
 
 const requests = new Map();
 
 // Measures the time it takes for a source to load
 const loadSourceHistogram = "DEVTOOLS_DEBUGGER_LOAD_SOURCE_MS";
 const telemetry = new Telemetry();
 
 async function loadSource(state, source: Source, { sourceMaps, client }) {
-  const { id } = source;
   if (isOriginal(source)) {
     return sourceMaps.getOriginalSourceText(source);
   }
 
-  const sourceActors = getSourceActors(state, id);
-  if (!sourceActors.length) {
+  if (!source.actors.length) {
     throw new Error("No source actor for loadSource");
   }
 
-  const response = await client.sourceContents(sourceActors[0]);
+  const response = await client.sourceContents(source.actors[0]);
   telemetry.finish(loadSourceHistogram, source);
 
   return {
-    id,
+    id: source.id,
     text: response.source,
     contentType: response.contentType || "text/javascript"
   };
 }
 
 /**
  * @memberof actions/sources
  * @static
--- a/devtools/client/debugger/new/src/actions/sources/newSources.js
+++ b/devtools/client/debugger/new/src/actions/sources/newSources.js
@@ -16,58 +16,58 @@ import { toggleBlackBox } from "./blackb
 import { syncBreakpoint } from "../breakpoints";
 import { loadSourceText } from "./loadSourceText";
 import { togglePrettyPrint } from "./prettyPrint";
 import { selectLocation } from "../sources";
 import { getRawSourceURL, isPrettyURL, isOriginal } from "../../utils/source";
 import {
   getBlackBoxList,
   getSource,
-  hasSourceActor,
   getPendingSelectedLocation,
   getPendingBreakpointsForSource
 } from "../../selectors";
 
 import { prefs } from "../../utils/prefs";
 import sourceQueue from "../../utils/source-queue";
 
 import type { Source, SourceId } from "../../types";
 import type { Action, ThunkArgs } from "../types";
-import type { CreateSourceResult } from "../../client/firefox/types";
 
 function createOriginalSource(
   originalUrl,
   generatedSource,
   sourceMaps
 ): Source {
   return {
     url: originalUrl,
     relativeUrl: originalUrl,
     id: generatedToOriginalId(generatedSource.id, originalUrl),
     isPrettyPrinted: false,
     isWasm: false,
     isBlackBoxed: false,
     loadedState: "unloaded",
-    introductionUrl: null
+    introductionUrl: null,
+    isExtension: false,
+    actors: []
   };
 }
 
 function loadSourceMaps(sources: Source[]) {
   return async function({
     dispatch,
     sourceMaps
   }: ThunkArgs): Promise<Promise<Source>[]> {
     if (!prefs.clientSourceMapsEnabled) {
       return [];
     }
 
     const sourceList = await Promise.all(
       sources.map(async ({ id }) => {
         const originalSources = await dispatch(loadSourceMap(id));
-        sourceQueue.queueSources(originalSources.map(source => ({ source })));
+        sourceQueue.queueSources(originalSources);
         return originalSources;
       })
     );
 
     await sourceQueue.flush();
     return flatten(sourceList);
   };
 }
@@ -198,46 +198,34 @@ function restoreBlackBoxedSources(source
   };
 }
 
 /**
  * Handler for the debugger client's unsolicited newSource notification.
  * @memberof actions/sources
  * @static
  */
-export function newSource(source: CreateSourceResult) {
+export function newSource(source: Source) {
   return async ({ dispatch }: ThunkArgs) => {
     await dispatch(newSources([source]));
   };
 }
 
-export function newSources(createdSources: CreateSourceResult[]) {
+export function newSources(foundSources: Source[]) {
   return async ({ dispatch, getState }: ThunkArgs) => {
-    // Find any sources we haven't seen before.
-    const sources = createdSources
-      .map(csr => csr.source)
-      .filter(source => !getSource(getState(), source.id));
-
-    // Find any source actors we haven't seen before.
-    const sourceActors = createdSources
-      .map(csr => csr.sourceActor)
-      .filter(
-        sourceActor => sourceActor && !hasSourceActor(getState(), sourceActor)
-      );
-
-    if (sources.length == 0 && sourceActors.length == 0) {
-      return;
-    }
-
-    dispatch({ type: "ADD_SOURCES", sources, sourceActors });
+    const sources = foundSources.filter(
+      source => !getSource(getState(), source.id)
+    );
 
     if (sources.length == 0) {
       return;
     }
 
+    dispatch({ type: "ADD_SOURCES", sources });
+
     for (const source of sources) {
       dispatch(checkSelectedSource(source.id));
     }
 
     // We would like to restore the blackboxed state
     // after loading all states to make sure the correctness.
     dispatch(restoreBlackBoxedSources(sources));
 
--- a/devtools/client/debugger/new/src/actions/sources/prettyPrint.js
+++ b/devtools/client/debugger/new/src/actions/sources/prettyPrint.js
@@ -3,30 +3,29 @@
  * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
 
 // @flow
 
 import assert from "../../utils/assert";
 import { recordEvent } from "../../utils/telemetry";
 import { remapBreakpoints } from "../breakpoints";
 
-import { setPausePoints, setSymbols } from "../ast";
+import { setSymbols } from "../ast";
 import { prettyPrint } from "../../workers/pretty-print";
 import { setSource } from "../../workers/parser";
 import { getPrettySourceURL, isLoaded } from "../../utils/source";
 import { loadSourceText } from "./loadSourceText";
 import { mapFrames } from "../pause";
 import { selectSpecificLocation } from "../sources";
 
 import {
   getSource,
   getSourceFromId,
   getSourceByURL,
-  getSelectedLocation,
-  getSourceActors
+  getSelectedLocation
 } from "../../selectors";
 
 import type { Action, ThunkArgs } from "../types";
 import { selectSource } from "./select";
 import type { JsSource } from "../../types";
 
 export function createPrettySource(sourceId: string) {
   return async ({ dispatch, getState, sourceMaps }: ThunkArgs) => {
@@ -38,29 +37,30 @@ export function createPrettySource(sourc
       url,
       relativeUrl: url,
       id,
       isBlackBoxed: false,
       isPrettyPrinted: true,
       isWasm: false,
       contentType: "text/javascript",
       loadedState: "loading",
-      introductionUrl: null
+      introductionUrl: null,
+      isExtension: false,
+      actors: []
     };
 
     dispatch(({ type: "ADD_SOURCE", source: prettySource }: Action));
     dispatch(selectSource(prettySource.id));
 
     const { code, mappings } = await prettyPrint({ source, url });
     await sourceMaps.applySourceMap(source.id, url, code, mappings);
 
     // The source map URL service used by other devtools listens to changes to
     // sources based on their actor IDs, so apply the mapping there too.
-    const sourceActors = getSourceActors(getState(), sourceId);
-    for (const sourceActor of sourceActors) {
+    for (const sourceActor of source.actors) {
       await sourceMaps.applySourceMap(sourceActor.actor, url, code, mappings);
     }
 
     const loadedPrettySource: JsSource = {
       ...prettySource,
       text: code,
       loadedState: "loaded"
     };
@@ -120,17 +120,16 @@ export function togglePrettyPrint(source
         selectSpecificLocation({ ...options.location, sourceId: _sourceId })
       );
     }
 
     const newPrettySource = await dispatch(createPrettySource(sourceId));
 
     await dispatch(remapBreakpoints(sourceId));
     await dispatch(mapFrames());
-    await dispatch(setPausePoints(newPrettySource.id));
     await dispatch(setSymbols(newPrettySource.id));
 
     dispatch(
       selectSpecificLocation({
         ...options.location,
         sourceId: newPrettySource.id
       })
     );
--- a/devtools/client/debugger/new/src/actions/sources/tests/__snapshots__/prettyPrint.spec.js.snap
+++ b/devtools/client/debugger/new/src/actions/sources/tests/__snapshots__/prettyPrint.spec.js.snap
@@ -1,12 +1,13 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`sources - pretty print returns a pretty source for a minified file 1`] = `
 Object {
+  "actors": Array [],
   "contentType": "text/javascript",
   "error": undefined,
   "id": "base.js/originalSource-36c718d4bde9a75edb388ff7733efe7f",
   "introductionUrl": null,
   "isBlackBoxed": false,
   "isExtension": false,
   "isPrettyPrinted": true,
   "isWasm": false,
--- a/devtools/client/debugger/new/src/actions/sources/tests/blackbox.spec.js
+++ b/devtools/client/debugger/new/src/actions/sources/tests/blackbox.spec.js
@@ -11,28 +11,28 @@ import {
   makeSource
 } from "../../../utils/test-head";
 
 describe("blackbox", () => {
   it("should blackbox a source", async () => {
     const store = createStore({ blackBox: async () => true });
     const { dispatch, getState } = store;
 
-    const foo1CSR = makeSource("foo1");
-    await dispatch(actions.newSource(foo1CSR));
-    await dispatch(actions.toggleBlackBox(foo1CSR.source));
+    const foo1Source = makeSource("foo1");
+    await dispatch(actions.newSource(foo1Source));
+    await dispatch(actions.toggleBlackBox(foo1Source));
 
     const fooSource = selectors.getSource(getState(), "foo1");
 
     if (!fooSource) {
       throw new Error("foo should exist");
     }
 
-    const thread = (foo1CSR.sourceActor: any).thread;
-    const relativeSources = selectors.getRelativeSourcesForThread(
+    const thread = foo1Source.actors[0].thread;
+    const displayedSources = selectors.getDisplayedSourcesForThread(
       getState(),
       thread
     );
 
-    expect(relativeSources[fooSource.id].isBlackBoxed).toEqual(true);
+    expect(displayedSources[fooSource.id].isBlackBoxed).toEqual(true);
     expect(fooSource.isBlackBoxed).toEqual(true);
   });
 });
--- a/devtools/client/debugger/new/src/actions/sources/tests/loadSource.spec.js
+++ b/devtools/client/debugger/new/src/actions/sources/tests/loadSource.spec.js
@@ -12,29 +12,29 @@ import {
 } from "../../../utils/test-head";
 import { sourceThreadClient } from "../../tests/helpers/threadClient.js";
 
 describe("loadSourceText", () => {
   it("should load source text", async () => {
     const store = createStore(sourceThreadClient);
     const { dispatch, getState } = store;
 
-    const foo1CSR = makeSource("foo1");
-    await dispatch(actions.newSource(foo1CSR));
-    await dispatch(actions.loadSourceText(foo1CSR.source));
+    const foo1Source = makeSource("foo1");
+    await dispatch(actions.newSource(foo1Source));
+    await dispatch(actions.loadSourceText(foo1Source));
     const fooSource = selectors.getSource(getState(), "foo1");
 
     if (!fooSource || typeof fooSource.text != "string") {
       throw new Error("bad fooSource");
     }
     expect(fooSource.text.indexOf("return foo1")).not.toBe(-1);
 
-    const foo2CSR = makeSource("foo2");
-    await dispatch(actions.newSource(foo2CSR));
-    await dispatch(actions.loadSourceText(foo2CSR.source));
+    const baseFoo2Source = makeSource("foo2");
+    await dispatch(actions.newSource(baseFoo2Source));
+    await dispatch(actions.loadSourceText(baseFoo2Source));
     const foo2Source = selectors.getSource(getState(), "foo2");
 
     if (!foo2Source || typeof foo2Source.text != "string") {
       throw new Error("bad fooSource");
     }
     expect(foo2Source.text.indexOf("return foo2")).not.toBe(-1);
   });
 
@@ -44,19 +44,19 @@ describe("loadSourceText", () => {
     const { dispatch, getState } = createStore({
       sourceContents: () =>
         new Promise(r => {
           count++;
           resolve = r;
         })
     });
     const id = "foo";
-    const csr = makeSource(id, { loadedState: "unloaded" });
+    const baseSource = makeSource(id, { loadedState: "unloaded" });
 
-    await dispatch(actions.newSource(csr));
+    await dispatch(actions.newSource(baseSource));
 
     let source = selectors.getSource(getState(), id);
     dispatch(actions.loadSourceText(source));
 
     source = selectors.getSource(getState(), id);
     const loading = dispatch(actions.loadSourceText(source));
 
     if (!resolve) {
@@ -76,19 +76,19 @@ describe("loadSourceText", () => {
     const { dispatch, getState } = createStore({
       sourceContents: () =>
         new Promise(r => {
           count++;
           resolve = r;
         })
     });
     const id = "foo";
-    const csr = makeSource(id, { loadedState: "unloaded" });
+    const baseSource = makeSource(id, { loadedState: "unloaded" });
 
-    await dispatch(actions.newSource(csr));
+    await dispatch(actions.newSource(baseSource));
     let source = selectors.getSource(getState(), id);
     const loading = dispatch(actions.loadSourceText(source));
 
     if (!resolve) {
       throw new Error("no resolve");
     }
     resolve({ source: "yay", contentType: "text/javascript" });
     await loading;
@@ -99,42 +99,42 @@ describe("loadSourceText", () => {
 
     source = selectors.getSource(getState(), id);
     expect(source && source.text).toEqual("yay");
   });
 
   it("should cache subsequent source text loads", async () => {
     const { dispatch, getState } = createStore(sourceThreadClient);
 
-    const csr = makeSource("foo1");
-    await dispatch(actions.loadSourceText(csr.source));
+    const source = makeSource("foo1");
+    await dispatch(actions.loadSourceText(source));
     const prevSource = selectors.getSource(getState(), "foo1");
 
     await dispatch(actions.loadSourceText(prevSource));
     const curSource = selectors.getSource(getState(), "foo1");
 
     expect(prevSource === curSource).toBeTruthy();
   });
 
   it("should indicate a loading source", async () => {
     const { dispatch, getState } = createStore(sourceThreadClient);
 
     // Don't block on this so we can check the loading state.
-    const csr = makeSource("foo1");
-    dispatch(actions.loadSourceText(csr.source));
+    const source = makeSource("foo1");
+    dispatch(actions.loadSourceText(source));
     const fooSource = selectors.getSource(getState(), "foo1");
     expect(fooSource && fooSource.loadedState).toEqual("loading");
   });
 
   it("should indicate an errored source text", async () => {
     const { dispatch, getState } = createStore(sourceThreadClient);
 
-    const csr = makeSource("bad-id");
-    await dispatch(actions.newSource(csr));
-    await dispatch(actions.loadSourceText(csr.source));
+    const source = makeSource("bad-id");
+    await dispatch(actions.newSource(source));
+    await dispatch(actions.loadSourceText(source));
     const badSource = selectors.getSource(getState(), "bad-id");
 
     if (!badSource || !badSource.error) {
       throw new Error("bad badSource");
     }
     expect(badSource.error.indexOf("unknown source")).not.toBe(-1);
   });
 });
--- a/devtools/client/debugger/new/src/actions/sources/tests/newSources.spec.js
+++ b/devtools/client/debugger/new/src/actions/sources/tests/newSources.spec.js
@@ -41,37 +41,37 @@ describe("sources - new sources", () => 
     await dispatch(actions.newSource(makeSource("base.js")));
     await dispatch(actions.newSource(makeSource("base.js")));
 
     expect(getSourceCount(getState())).toEqual(1);
   });
 
   it("should automatically select a pending source", async () => {
     const { dispatch, getState } = createStore(threadClient);
-    const baseCSR = makeSource("base.js");
-    await dispatch(actions.selectSourceURL(baseCSR.source.url));
+    const baseSource = makeSource("base.js");
+    await dispatch(actions.selectSourceURL(baseSource.url));
 
     expect(getSelectedSource(getState())).toBe(undefined);
-    await dispatch(actions.newSource(baseCSR));
+    await dispatch(actions.newSource(baseSource));
 
     const selected = getSelectedSource(getState());
-    expect(selected && selected.url).toBe(baseCSR.source.url);
+    expect(selected && selected.url).toBe(baseSource.url);
   });
 
   it("should add original sources", async () => {
     const { dispatch, getState } = createStore(
       threadClient,
       {},
       {
         getOriginalURLs: async () => ["magic.js"]
       }
     );
 
-    const baseCSR = makeSource("base.js", { sourceMapURL: "base.js.map" });
-    await dispatch(actions.newSource(baseCSR));
+    const baseSource = makeSource("base.js", { sourceMapURL: "base.js.map" });
+    await dispatch(actions.newSource(baseSource));
     const magic = getSourceByURL(getState(), "magic.js");
     expect(magic && magic.url).toEqual("magic.js");
   });
 
   // eslint-disable-next-line
   it("should not attempt to fetch original sources if it's missing a source map url", async () => {
     const getOriginalURLs = jest.fn();
     const { dispatch } = createStore(threadClient, {}, { getOriginalURLs });
@@ -90,18 +90,18 @@ describe("sources - new sources", () => 
   it("should process new sources immediately, without waiting for source maps to be fetched first", async () => {
     const { dispatch, getState } = createStore(
       threadClient,
       {},
       {
         getOriginalURLs: async () => new Promise(_ => {})
       }
     );
-    const baseCSR = makeSource("base.js", { sourceMapURL: "base.js.map" });
-    await dispatch(actions.newSource(baseCSR));
+    const baseSource = makeSource("base.js", { sourceMapURL: "base.js.map" });
+    await dispatch(actions.newSource(baseSource));
     expect(getSourceCount(getState())).toEqual(1);
     const base = getSource(getState(), "base.js");
     expect(base && base.id).toEqual("base.js");
   });
 
   // eslint-disable-next-line
   it("shouldn't let one slow loading source map delay all the other source maps", async () => {
     const dbg = createStore(
--- a/devtools/client/debugger/new/src/actions/sources/tests/prettyPrint.spec.js
+++ b/devtools/client/debugger/new/src/actions/sources/tests/prettyPrint.spec.js
@@ -13,33 +13,33 @@ import {
 import { createPrettySource } from "../prettyPrint";
 import { sourceThreadClient } from "../../tests/helpers/threadClient.js";
 
 describe("sources - pretty print", () => {
   const { dispatch, getState } = createStore(sourceThreadClient);
 
   it("returns a pretty source for a minified file", async () => {
     const url = "base.js";
-    const csr = makeSource(url);
-    await dispatch(actions.newSource(csr));
-    await dispatch(createPrettySource(csr.source.id));
+    const source = makeSource(url);
+    await dispatch(actions.newSource(source));
+    await dispatch(createPrettySource(source.id));
 
-    const prettyURL = `${csr.source.url}:formatted`;
+    const prettyURL = `${source.url}:formatted`;
     const pretty = selectors.getSourceByURL(getState(), prettyURL);
     expect(pretty && pretty.contentType).toEqual("text/javascript");
     expect(pretty && pretty.url.includes(prettyURL)).toEqual(true);
     expect(pretty).toMatchSnapshot();
   });
 
   it("should create a source when first toggling pretty print", async () => {
-    const csr = makeSource("foobar.js", { loadedState: "loaded" });
-    await dispatch(actions.togglePrettyPrint(csr.source.id));
+    const source = makeSource("foobar.js", { loadedState: "loaded" });
+    await dispatch(actions.togglePrettyPrint(source.id));
     expect(selectors.getSourceCount(getState())).toEqual(2);
   });
 
   it("should not make a second source when toggling pretty print", async () => {
-    const csr = makeSource("foobar.js", { loadedState: "loaded" });
-    await dispatch(actions.togglePrettyPrint(csr.source.id));
+    const source = makeSource("foobar.js", { loadedState: "loaded" });
+    await dispatch(actions.togglePrettyPrint(source.id));
     expect(selectors.getSourceCount(getState())).toEqual(2);
-    await dispatch(actions.togglePrettyPrint(csr.source.id));
+    await dispatch(actions.togglePrettyPrint(source.id));
     expect(selectors.getSourceCount(getState())).toEqual(2);
   });
 });
--- a/devtools/client/debugger/new/src/actions/sources/tests/select.spec.js
+++ b/devtools/client/debugger/new/src/actions/sources/tests/select.spec.js
@@ -74,36 +74,36 @@ describe("sources", () => {
     );
     const locations = getOutOfScopeLocations(getState());
     expect(locations).toHaveLength(1);
   });
 
   it("should select next tab on tab closed if no previous tab", async () => {
     const { dispatch, getState } = createStore(sourceThreadClient);
 
-    const fooCSR = makeSource("foo.js");
+    const fooSource = makeSource("foo.js");
 
-    await dispatch(actions.newSource(fooCSR));
+    await dispatch(actions.newSource(fooSource));
     await dispatch(actions.newSource(makeSource("bar.js")));
     await dispatch(actions.newSource(makeSource("baz.js")));
 
     // 3rd tab
     await dispatch(actions.selectLocation(initialLocation("foo.js")));
 
     // 2nd tab
     await dispatch(actions.selectLocation(initialLocation("bar.js")));
 
     // 1st tab
     await dispatch(actions.selectLocation(initialLocation("baz.js")));
 
     // 3rd tab is reselected
     await dispatch(actions.selectLocation(initialLocation("foo.js")));
 
     // closes the 1st tab, which should have no previous tab
-    await dispatch(actions.closeTab(fooCSR.source));
+    await dispatch(actions.closeTab(fooSource));
 
     const selected = getSelectedSource(getState());
     expect(selected && selected.id).toBe("bar.js");
     expect(getSourceTabs(getState())).toHaveLength(2);
   });
 
   it("should open a tab for the source", async () => {
     const { dispatch, getState } = createStore(sourceThreadClient);
@@ -121,17 +121,17 @@ describe("sources", () => {
     await dispatch(actions.newSource(makeSource("bar.js")));
 
     const bazSource = makeSource("baz.js");
     await dispatch(actions.newSource(bazSource));
 
     await dispatch(actions.selectLocation(initialLocation("foo.js")));
     await dispatch(actions.selectLocation(initialLocation("bar.js")));
     await dispatch(actions.selectLocation(initialLocation("baz.js")));
-    await dispatch(actions.closeTab(bazSource.source));
+    await dispatch(actions.closeTab(bazSource));
 
     const selected = getSelectedSource(getState());
     expect(selected && selected.id).toBe("bar.js");
     expect(getSourceTabs(getState())).toHaveLength(2);
   });
 
   it("should keep the selected source when other tab closed", async () => {
     const { dispatch, getState } = createStore(sourceThreadClient);
@@ -148,38 +148,38 @@ describe("sources", () => {
     // 2nd tab
     await dispatch(actions.selectLocation(initialLocation("bar.js")));
 
     // 1st tab
     await dispatch(actions.selectLocation(initialLocation("baz.js")));
 
     // 3rd tab is reselected
     await dispatch(actions.selectLocation(initialLocation("foo.js")));
-    await dispatch(actions.closeTab(bazSource.source));
+    await dispatch(actions.closeTab(bazSource));
 
     const selected = getSelectedSource(getState());
     expect(selected && selected.id).toBe("foo.js");
     expect(getSourceTabs(getState())).toHaveLength(2);
   });
 
   it("should not select new sources that lack a URL", async () => {
     const { dispatch, getState } = createStore(sourceThreadClient);
 
-    const csr = makeSource("foo");
-    csr.source.url = "";
-    await dispatch(actions.newSource(csr));
+    const source = makeSource("foo");
+    source.url = "";
+    await dispatch(actions.newSource(source));
 
     expect(getSourceCount(getState())).toEqual(1);
     const selectedLocation = getSelectedLocation(getState());
     expect(selectedLocation).toEqual(undefined);
   });
 
   it("sets and clears selected location correctly", () => {
     const { dispatch, getState } = createStore(sourceThreadClient);
-    const source = makeSource("testSource").source;
+    const source = makeSource("testSource");
     const location = ({ test: "testLocation" }: any);
 
     // set value
     dispatch(actions.setSelectedLocation(source, location));
     expect(getSelectedLocation(getState())).toEqual({
       sourceId: source.id,
       ...location
     });
@@ -206,85 +206,83 @@ describe("sources", () => {
     dispatch(actions.clearSelectedLocation());
     const clearResult = getState().sources.pendingSelectedLocation;
     expect(clearResult).toEqual({ url: "" });
   });
 
   it("should keep the generated the viewing context", async () => {
     const store = createStore(sourceThreadClient);
     const { dispatch, getState } = store;
-    const baseCSR = makeSource("base.js");
-    await dispatch(actions.newSource(baseCSR));
+    const baseSource = makeSource("base.js");
+    await dispatch(actions.newSource(baseSource));
 
     await dispatch(
-      actions.selectLocation({ sourceId: baseCSR.source.id, line: 1 })
+      actions.selectLocation({ sourceId: baseSource.id, line: 1 })
     );
 
     const selected = getSelectedSource(getState());
-    expect(selected && selected.id).toBe(baseCSR.source.id);
-    await waitForState(store, state => getSymbols(state, baseCSR.source));
+    expect(selected && selected.id).toBe(baseSource.id);
+    await waitForState(store, state => getSymbols(state, baseSource));
   });
 
   it("should keep the original the viewing context", async () => {
     const { dispatch, getState } = createStore(
       sourceThreadClient,
       {},
       {
         getOriginalLocation: async location => ({ ...location, line: 12 }),
         getGeneratedLocation: async location => ({ ...location, line: 12 }),
         getOriginalSourceText: async () => ({ source: "" })
       }
     );
 
-    const baseCSR = makeSource("base.js");
-    await dispatch(actions.newSource(baseCSR));
+    const baseSource = makeSource("base.js");
+    await dispatch(actions.newSource(baseSource));
 
     const originalBaseSource = makeOriginalSource("base.js");
     await dispatch(actions.newSource(originalBaseSource));
 
-    await dispatch(actions.selectSource(originalBaseSource.source.id));
+    await dispatch(actions.selectSource(originalBaseSource.id));
 
-    const fooCSR = makeSource("foo.js");
-    await dispatch(actions.newSource(fooCSR));
-    await dispatch(
-      actions.selectLocation({ sourceId: fooCSR.source.id, line: 1 })
-    );
+    const fooSource = makeSource("foo.js");
+    await dispatch(actions.newSource(fooSource));
+    await dispatch(actions.selectLocation({ sourceId: fooSource.id, line: 1 }));
 
     const selected = getSelectedLocation(getState());
     expect(selected && selected.line).toBe(12);
   });
 
   it("should change the original the viewing context", async () => {
     const { dispatch, getState } = createStore(
       sourceThreadClient,
       {},
       { getOriginalLocation: async location => ({ ...location, line: 12 }) }
     );
 
-    const baseCSR = makeOriginalSource("base.js");
-    await dispatch(actions.newSource(baseCSR));
-    await dispatch(actions.selectSource(baseCSR.source.id));
+    const baseSource = makeOriginalSource("base.js");
+    await dispatch(actions.newSource(baseSource));
+    await dispatch(actions.selectSource(baseSource.id));
 
     await dispatch(
       actions.selectSpecificLocation({
-        sourceId: baseCSR.source.id,
+        sourceId: baseSource.id,
         line: 1
       })
     );
 
     const selected = getSelectedLocation(getState());
     expect(selected && selected.line).toBe(1);
   });
 
   describe("selectSourceURL", () => {
     it("should automatically select a pending source", async () => {
       const { dispatch, getState } = createStore(sourceThreadClient);
-      const baseCSR = makeSource("base.js");
-      await dispatch(actions.selectSourceURL(baseCSR.source.url));
+      const baseSource = makeSource("base.js");
+      await dispatch(actions.selectSourceURL(baseSource.url));
 
       expect(getSelectedSource(getState())).toBe(undefined);
-      await dispatch(actions.newSource(baseCSR));
+      await dispatch(actions.newSource(baseSource));
 
       const selected = getSelectedSource(getState());
-      expect(selected && selected.url).toBe(baseCSR.source.url);
+      expect(selected && selected.url).toBe(baseSource.url);
     });
   });
 });
--- a/devtools/client/debugger/new/src/actions/tabs.js
+++ b/devtools/client/debugger/new/src/actions/tabs.js
@@ -10,18 +10,18 @@
  */
 
 import { isOriginalId } from "devtools-source-map";
 
 import { removeDocument } from "../utils/editor";
 import { selectSource } from "./sources";
 
 import {
-  getSourcesByURLs,
   getSourceTabs,
+  getSourceByURL,
   getNewSelectedSourceId,
   removeSourceFromTabList,
   removeSourcesFromTabList
 } from "../selectors";
 
 import type { Action, ThunkArgs } from "./types";
 import type { Source } from "../types";
 
@@ -76,17 +76,19 @@ export function closeTab(source: Source)
 }
 
 /**
  * @memberof actions/tabs
  * @static
  */
 export function closeTabs(urls: string[]) {
   return ({ dispatch, getState, client }: ThunkArgs) => {
-    const sources = getSourcesByURLs(getState(), urls);
+    const sources = urls
+      .map(url => getSourceByURL(getState(), url))
+      .filter(Boolean);
     sources.map(source => removeDocument(source.id));
 
     const tabs = removeSourcesFromTabList(getSourceTabs(getState()), sources);
     dispatch(({ type: "CLOSE_TABS", sources, tabs }: Action));
 
     const sourceId = getNewSelectedSourceId(getState(), tabs);
     dispatch(selectSource(sourceId));
   };
--- a/devtools/client/debugger/new/src/actions/tests/__snapshots__/ast.spec.js.snap
+++ b/devtools/client/debugger/new/src/actions/tests/__snapshots__/ast.spec.js.snap
@@ -35,28 +35,16 @@ Array [
   6,
   7,
   10,
   11,
   12,
 ]
 `;
 
-exports[`ast setPausePoints scopes 1`] = `
-Array [
-  1,
-  2,
-  6,
-  7,
-  10,
-  11,
-  12,
-]
-`;
-
 exports[`ast setSymbols when the source is loaded should be able to set symbols 1`] = `
 Object {
   "callExpressions": Array [],
   "classes": Array [],
   "comments": Array [],
   "functions": Array [
     Object {
       "identifier": Object {
--- a/devtools/client/debugger/new/src/actions/tests/ast.spec.js
+++ b/devtools/client/debugger/new/src/actions/tests/ast.spec.js
@@ -14,31 +14,29 @@ import {
   makeFrame,
   waitForState
 } from "../../utils/test-head";
 
 import readFixture from "./helpers/readFixture";
 const {
   getSource,
   getSymbols,
-  getEmptyLines,
   getOutOfScopeLocations,
   getSourceMetaData,
   getInScopeLines,
   isSymbolsLoading
 } = selectors;
 
 import { prefs } from "../../utils/prefs";
 
 const threadClient = {
   sourceContents: async ({ source }) => ({
     source: sourceTexts[source],
     contentType: "text/javascript"
   }),
-  setPausePoints: async () => {},
   getFrameScopes: async () => {},
   evaluate: async expression => ({ result: evaluationResult[expression] }),
   evaluateExpressions: async expressions =>
     expressions.map(expression => ({ result: evaluationResult[expression] }))
 };
 
 const sourceMaps = {
   getOriginalSourceText: async ({ id }) => ({
@@ -57,97 +55,74 @@ const sourceTexts = {
 };
 
 const evaluationResult = {
   "this.bazz": { actor: "bazz", preview: {} },
   this: { actor: "this", preview: {} }
 };
 
 describe("ast", () => {
-  describe("setPausePoints", () => {
-    it("scopes", async () => {
-      const store = createStore(threadClient);
-      const { dispatch, getState } = store;
-      const csr = makeSource("scopes.js");
-      await dispatch(actions.newSource(csr));
-      await dispatch(actions.loadSourceText(csr.source));
-      await dispatch(actions.setPausePoints("scopes.js"));
-      await waitForState(store, state => {
-        const lines = getEmptyLines(state, csr.source.id);
-        return lines && lines.length > 0;
-      });
-
-      const emptyLines = getEmptyLines(getState(), csr.source.id);
-      expect(emptyLines).toMatchSnapshot();
-    });
-  });
-
   describe("setSourceMetaData", () => {
     it("should detect react components", async () => {
       const store = createStore(threadClient, {}, sourceMaps);
       const { dispatch, getState } = store;
-      const csr = makeOriginalSource("reactComponent.js");
+      const source = makeOriginalSource("reactComponent.js");
 
       await dispatch(actions.newSource(makeSource("reactComponent.js")));
 
-      await dispatch(actions.newSource(csr));
+      await dispatch(actions.newSource(source));
 
-      await dispatch(
-        actions.loadSourceText(getSource(getState(), csr.source.id))
-      );
-      await dispatch(actions.setSourceMetaData(csr.source.id));
+      await dispatch(actions.loadSourceText(getSource(getState(), source.id)));
+      await dispatch(actions.setSourceMetaData(source.id));
 
       await waitForState(store, state => {
-        const metaData = getSourceMetaData(state, csr.source.id);
+        const metaData = getSourceMetaData(state, source.id);
         return metaData && metaData.framework;
       });
 
-      const sourceMetaData = getSourceMetaData(getState(), csr.source.id);
+      const sourceMetaData = getSourceMetaData(getState(), source.id);
       expect(sourceMetaData.framework).toBe("React");
     });
 
     it("should not give false positive on non react components", async () => {
       const store = createStore(threadClient);
       const { dispatch, getState } = store;
       const base = makeSource("base.js");
       await dispatch(actions.newSource(base));
-      await dispatch(actions.loadSourceText(base.source));
+      await dispatch(actions.loadSourceText(base));
       await dispatch(actions.setSourceMetaData("base.js"));
 
-      const sourceMetaData = getSourceMetaData(getState(), base.source.id);
+      const sourceMetaData = getSourceMetaData(getState(), base.id);
       expect(sourceMetaData.framework).toBe(undefined);
     });
   });
 
   describe("setSymbols", () => {
     describe("when the source is loaded", () => {
       it("should be able to set symbols", async () => {
         const store = createStore(threadClient);
         const { dispatch, getState } = store;
         const base = makeSource("base.js");
         await dispatch(actions.newSource(base));
-        await dispatch(actions.loadSourceText(base.source));
+        await dispatch(actions.loadSourceText(base));
         await dispatch(actions.setSymbols("base.js"));
-        await waitForState(
-          store,
-          state => !isSymbolsLoading(state, base.source)
-        );
+        await waitForState(store, state => !isSymbolsLoading(state, base));
 
-        const baseSymbols = getSymbols(getState(), base.source);
+        const baseSymbols = getSymbols(getState(), base);
         expect(baseSymbols).toMatchSnapshot();
       });
     });
 
     describe("when the source is not loaded", () => {
       it("should return null", async () => {
         const { getState, dispatch } = createStore(threadClient);
         const base = makeSource("base.js");
         await dispatch(actions.newSource(base));
 
-        const baseSymbols = getSymbols(getState(), base.source);
+        const baseSymbols = getSymbols(getState(), base);
         expect(baseSymbols).toEqual(null);
       });
     });
 
     describe("when there is no source", () => {
       it("should return null", async () => {
         const { getState } = createStore(threadClient);
         const baseSymbols = getSymbols(getState());
@@ -159,18 +134,18 @@ describe("ast", () => {
   describe("getOutOfScopeLocations", () => {
     beforeEach(async () => {
       prefs.autoPrettyPrint = false;
     });
 
     it("with selected line", async () => {
       const store = createStore(threadClient);
       const { dispatch, getState } = store;
-      const csr = makeSource("scopes.js");
-      await dispatch(actions.newSource(csr));
+      const source = makeSource("scopes.js");
+      await dispatch(actions.newSource(source));
 
       await dispatch(
         actions.selectLocation({ sourceId: "scopes.js", line: 5 })
       );
 
       const frame = makeFrame({ id: "1", sourceId: "scopes.js" });
       await dispatch(
         actions.paused({
--- a/devtools/client/debugger/new/src/actions/tests/expressions.spec.js
+++ b/devtools/client/debugger/new/src/actions/tests/expressions.spec.js
@@ -121,16 +121,18 @@ describe("expressions", () => {
     expect(selectors.getExpression(getState(), "foo").value).toBe("bla");
     expect(selectors.getExpression(getState(), "bar").value).toBe("bla");
   });
 
   it("should evaluate expressions in specific scope", async () => {
     const { dispatch, getState } = createStore(mockThreadClient);
     await createFrames(dispatch);
 
+    await dispatch(actions.newSource(makeSource("source")));
+
     await dispatch(actions.addExpression("foo"));
     await dispatch(actions.addExpression("bar"));
 
     expect(selectors.getExpression(getState(), "foo").value).toBe("boo");
     expect(selectors.getExpression(getState(), "bar").value).toBe("boo");
 
     await dispatch(actions.evaluateExpressions());
 
--- a/devtools/client/debugger/new/src/actions/tests/helpers/threadClient.js
+++ b/devtools/client/debugger/new/src/actions/tests/helpers/threadClient.js
@@ -44,17 +44,16 @@ export const simpleMockThreadClient = {
   removeBreakpoint: (_id: string) => Promise.resolve(),
 
   setBreakpointOptions: (
     _id: string,
     _location: SourceActorLocation,
     _options: BreakpointOptions,
     _noSliding: boolean
   ) => Promise.resolve({ sourceId: "a", line: 5 }),
-  setPausePoints: () => Promise.resolve({}),
   sourceContents: ({
     source
   }: SourceActor): Promise<{| source: any, contentType: ?string |}> =>
     new Promise((resolve, reject) => {
       if (sources.includes(source)) {
         resolve(createSource(source));
       }
 
@@ -72,11 +71,10 @@ export const sourceThreadClient = {
         resolve(createSource(source));
       }
 
       reject(`unknown source: ${source}`);
     });
   },
   threadClient: async () => {},
   getFrameScopes: async () => {},
-  setPausePoints: async () => {},
   evaluateExpressions: async () => {}
 };
--- a/devtools/client/debugger/new/src/actions/tests/pending-breakpoints.spec.js
+++ b/devtools/client/debugger/new/src/actions/tests/pending-breakpoints.spec.js
@@ -50,19 +50,20 @@ import { makePendingLocationId } from ".
 
 describe("when adding breakpoints", () => {
   it("a corresponding pending breakpoint should be added", async () => {
     const { dispatch, getState } = createStore(
       simpleMockThreadClient,
       loadInitialState()
     );
 
-    const csr = makeOriginalSource("foo.js");
-    await dispatch(actions.newSource(csr));
-    await dispatch(actions.loadSourceText(csr.source));
+    const source = makeOriginalSource("foo.js");
+    await dispatch(actions.newSource(source));
+    await dispatch(actions.newSource(makeSource("foo.js")));
+    await dispatch(actions.loadSourceText(source));
 
     const bp = generateBreakpoint("foo.js");
     const id = makePendingLocationId(bp.location);
 
     await dispatch(actions.addBreakpoint(bp.location));
     const pendingBps = selectors.getPendingBreakpoints(getState());
 
     expect(selectors.getPendingBreakpointList(getState())).toHaveLength(2);
@@ -83,67 +84,72 @@ describe("when adding breakpoints", () =
     });
 
     it("add a corresponding pendingBreakpoint for each addition", async () => {
       const { dispatch, getState } = createStore(
         simpleMockThreadClient,
         loadInitialState()
       );
 
-      const csr1 = makeOriginalSource("foo");
-      const csr2 = makeOriginalSource("foo2");
+      const source1 = makeOriginalSource("foo");
+      const source2 = makeOriginalSource("foo2");
+
+      await dispatch(actions.newSource(makeSource("foo")));
+      await dispatch(actions.newSource(makeSource("foo2")));
 
-      await dispatch(actions.newSource(csr1));
-      await dispatch(actions.newSource(csr2));
+      await dispatch(actions.newSource(source1));
+      await dispatch(actions.newSource(source2));
 
-      await dispatch(actions.loadSourceText(csr1.source));
-      await dispatch(actions.loadSourceText(csr2.source));
+      await dispatch(actions.loadSourceText(source1));
+      await dispatch(actions.loadSourceText(source2));
 
       await dispatch(actions.addBreakpoint(breakpoint1.location));
       await dispatch(actions.addBreakpoint(breakpoint2.location));
 
       const pendingBps = selectors.getPendingBreakpoints(getState());
       expect(pendingBps[breakpointLocationId1]).toMatchSnapshot();
       expect(pendingBps[breakpointLocationId2]).toMatchSnapshot();
     });
 
     it("hidden breakponts do not create pending bps", async () => {
       const { dispatch, getState } = createStore(
         simpleMockThreadClient,
         loadInitialState()
       );
 
-      const csr = makeOriginalSource("foo");
-      await dispatch(actions.newSource(csr));
-      await dispatch(actions.loadSourceText(csr.source));
+      const source = makeOriginalSource("foo");
+      await dispatch(actions.newSource(makeSource("foo")));
+      await dispatch(actions.newSource(source));
+      await dispatch(actions.loadSourceText(source));
 
       await dispatch(
         actions.addBreakpoint(breakpoint1.location, { hidden: true })
       );
       const pendingBps = selectors.getPendingBreakpoints(getState());
 
       expect(pendingBps[breakpointLocationId1]).toBeUndefined();
     });
 
     it("remove a corresponding pending breakpoint when deleting", async () => {
       const { dispatch, getState } = createStore(
         simpleMockThreadClient,
         loadInitialState()
       );
 
       await dispatch(actions.newSource(makeSource("foo")));
+      await dispatch(actions.newSource(makeSource("foo2")));
 
-      const csr1 = makeOriginalSource("foo");
-      const csr2 = makeOriginalSource("foo2");
+      const source1 = makeOriginalSource("foo");
+      const source2 = makeOriginalSource("foo2");
 
-      await dispatch(actions.newSource(csr1));
-      await dispatch(actions.newSource(csr2));
+      await dispatch(actions.newSource(source1));
+      await dispatch(actions.newSource(source2));
 
-      await dispatch(actions.loadSourceText(csr1.source));
-      await dispatch(actions.loadSourceText(csr2.source));
+      await dispatch(actions.loadSourceText(source1));
+      await dispatch(actions.loadSourceText(source2));
 
       await dispatch(actions.addBreakpoint(breakpoint1.location));
       await dispatch(actions.addBreakpoint(breakpoint2.location));
       await dispatch(actions.removeBreakpoint(breakpoint1));
 
       const pendingBps = selectors.getPendingBreakpoints(getState());
       expect(pendingBps.hasOwnProperty(breakpointLocationId1)).toBe(false);
       expect(pendingBps.hasOwnProperty(breakpointLocationId2)).toBe(true);
@@ -155,19 +161,20 @@ describe("when changing an existing brea
   it("updates corresponding pendingBreakpoint", async () => {
     const { dispatch, getState } = createStore(
       simpleMockThreadClient,
       loadInitialState()
     );
     const bp = generateBreakpoint("foo");
     const id = makePendingLocationId(bp.location);
 
-    const csr = makeOriginalSource("foo");
-    await dispatch(actions.newSource(csr));
-    await dispatch(actions.loadSourceText(csr.source));
+    const source = makeOriginalSource("foo");
+    await dispatch(actions.newSource(source));
+    await dispatch(actions.newSource(makeSource("foo")));
+    await dispatch(actions.loadSourceText(source));
 
     await dispatch(actions.addBreakpoint(bp.location));
     await dispatch(
       actions.setBreakpointOptions(bp.location, { condition: "2" })
     );
     const bps = selectors.getPendingBreakpoints(getState());
     const breakpoint = bps[id];
     expect(breakpoint.options.condition).toBe("2");
@@ -178,37 +185,38 @@ describe("when changing an existing brea
       simpleMockThreadClient,
       loadInitialState()
     );
     const bp = generateBreakpoint("foo");
     const id = makePendingLocationId(bp.location);
 
     await dispatch(actions.newSource(makeSource("foo")));
 
-    const csr = makeOriginalSource("foo");
-    await dispatch(actions.newSource(csr));
-    await dispatch(actions.loadSourceText(csr.source));
+    const source = makeOriginalSource("foo");
+    await dispatch(actions.newSource(source));
+    await dispatch(actions.loadSourceText(source));
 
     await dispatch(actions.addBreakpoint(bp.location));
     await dispatch(actions.disableBreakpoint(bp));
     const bps = selectors.getPendingBreakpoints(getState());
     const breakpoint = bps[id];
     expect(breakpoint.disabled).toBe(true);
   });
 
   it("does not delete the pre-existing pendingBreakpoint", async () => {
     const { dispatch, getState } = createStore(
       simpleMockThreadClient,
       loadInitialState()
     );
     const bp = generateBreakpoint("foo.js");
 
-    const csr = makeOriginalSource("foo.js");
-    await dispatch(actions.newSource(csr));
-    await dispatch(actions.loadSourceText(csr.source));
+    const source = makeOriginalSource("foo.js");
+    await dispatch(actions.newSource(source));
+    await dispatch(actions.newSource(makeSource("foo.js")));
+    await dispatch(actions.loadSourceText(source));
 
     const id = makePendingLocationId(bp.location);
 
     await dispatch(actions.addBreakpoint(bp.location));
     await dispatch(
       actions.setBreakpointOptions(bp.location, { condition: "2" })
     );
     const bps = selectors.getPendingBreakpoints(getState());
@@ -231,132 +239,134 @@ describe("initializing when pending brea
     const { dispatch, getState } = createStore(
       simpleMockThreadClient,
       loadInitialState()
     );
     const bar = generateBreakpoint("bar.js");
 
     await dispatch(actions.newSource(makeSource("bar.js")));
 
-    const csr = makeOriginalSource("bar.js");
-    await dispatch(actions.newSource(csr));
-    await dispatch(actions.loadSourceText(csr.source));
+    const source = makeOriginalSource("bar.js");
+    await dispatch(actions.newSource(source));
+    await dispatch(actions.loadSourceText(source));
 
     await dispatch(actions.addBreakpoint(bar.location));
 
     const bps = selectors.getPendingBreakpointList(getState());
     expect(bps).toHaveLength(1);
   });
 
   it("adding bps doesn't remove existing pending breakpoints", async () => {
     const { dispatch, getState } = createStore(
       simpleMockThreadClient,
       loadInitialState()
     );
     const bp = generateBreakpoint("foo.js");
 
-    const csr = makeOriginalSource("foo.js");
-    await dispatch(actions.newSource(csr));
-    await dispatch(actions.loadSourceText(csr.source));
+    const source = makeOriginalSource("foo.js");
+    await dispatch(actions.newSource(source));
+    await dispatch(actions.newSource(makeSource("foo.js")));
+    await dispatch(actions.loadSourceText(source));
 
     await dispatch(actions.addBreakpoint(bp.location));
 
     const bps = selectors.getPendingBreakpointList(getState());
     expect(bps).toHaveLength(2);
   });
 });
 
 describe("initializing with disabled pending breakpoints in prefs", () => {
   it("syncs breakpoints with pending breakpoints", async () => {
     const store = createStore(
       simpleMockThreadClient,
       loadInitialState({ disabled: true })
     );
 
     const { getState, dispatch } = store;
-    const csr = makeOriginalSource("bar.js");
+    const source = makeOriginalSource("bar.js");
 
     await dispatch(actions.newSource(makeSource("bar.js")));
-    await dispatch(actions.newSource(csr));
-    await dispatch(actions.loadSourceText(csr.source));
+    await dispatch(actions.newSource(source));
+    await dispatch(actions.loadSourceText(source));
 
     await waitForState(store, state => {
-      const bps = selectors.getBreakpointsForSource(state, csr.source.id);
+      const bps = selectors.getBreakpointsForSource(state, source.id);
       return bps && Object.values(bps).length > 0;
     });
 
     const bp = selectors.getBreakpointForLocation(getState(), {
       line: 5,
       column: undefined,
-      sourceUrl: csr.source.url,
-      sourceId: csr.source.id
+      sourceUrl: source.url,
+      sourceId: source.id
     });
     if (!bp) {
       throw new Error("no bp");
     }
-    expect(bp.location.sourceId).toEqual(csr.source.id);
+    expect(bp.location.sourceId).toEqual(source.id);
     expect(bp.disabled).toEqual(true);
   });
 });
 
 describe("adding sources", () => {
   it("corresponding breakpoints are added for a single source", async () => {
     const store = createStore(simpleMockThreadClient, loadInitialState());
     const { getState, dispatch } = store;
 
     expect(selectors.getBreakpointCount(getState())).toEqual(0);
 
-    const csr = makeOriginalSource("bar.js");
+    const source = makeOriginalSource("bar.js");
 
     await dispatch(actions.newSource(makeSource("bar.js")));
-    await dispatch(actions.newSource(csr));
-    await dispatch(actions.loadSourceText(csr.source));
+    await dispatch(actions.newSource(source));
+    await dispatch(actions.loadSourceText(source));
 
     await waitForState(store, state => selectors.getBreakpointCount(state) > 0);
 
     expect(selectors.getBreakpointCount(getState())).toEqual(1);
   });
 
   it("corresponding breakpoints are added to the original source", async () => {
-    const csr = makeOriginalSource("bar.js", { sourceMapURL: "foo" });
+    const source = makeOriginalSource("bar.js", { sourceMapURL: "foo" });
     const store = createStore(simpleMockThreadClient, loadInitialState(), {
-      getOriginalURLs: async () => [csr.source.url],
+      getOriginalURLs: async () => [source.url],
       getOriginalSourceText: async () => ({ source: "" }),
       getGeneratedLocation: async (location, _source) => ({
         line: location.line,
         column: location.column,
         sourceId: _source.id
       }),
       getOriginalLocation: async location => location
     });
 
     const { getState, dispatch } = store;
 
     expect(selectors.getBreakpointCount(getState())).toEqual(0);
 
     await dispatch(actions.newSource(makeSource("bar.js")));
-    await dispatch(actions.newSource(csr));
+    await dispatch(actions.newSource(source));
 
     await waitForState(store, state => selectors.getBreakpointCount(state) > 0);
 
     expect(selectors.getBreakpointCount(getState())).toEqual(1);
   });
 
   it("add corresponding breakpoints for multiple sources", async () => {
     const store = createStore(simpleMockThreadClient, loadInitialState());
     const { getState, dispatch } = store;
 
     expect(selectors.getBreakpointCount(getState())).toEqual(0);
 
-    const csr1 = makeOriginalSource("bar.js");
-    const csr2 = makeOriginalSource("foo.js");
+    const source1 = makeOriginalSource("bar.js");
+    const source2 = makeOriginalSource("foo.js");
     await dispatch(actions.newSource(makeSource("bar.js")));
-    await dispatch(actions.newSources([csr1, csr2]));
-    await dispatch(actions.loadSourceText(csr1.source));
-    await dispatch(actions.loadSourceText(csr2.source));
+    await dispatch(actions.newSource(makeSource("foo.js")));
+    await dispatch(actions.newSources([source1, source2]));
+    await dispatch(actions.loadSourceText(source1));
+    await dispatch(actions.loadSourceText(source2));
 
     await waitForState(store, state => selectors.getBreakpointCount(state) > 0);
 
     // N.B. this test is kind of broken and creates different breakpoints for
     // the generated and original bar.js sources.
     expect(selectors.getBreakpointCount(getState())).toEqual(2);
   });
 });
--- a/devtools/client/debugger/new/src/actions/tests/project-text-search.spec.js
+++ b/devtools/client/debugger/new/src/actions/tests/project-text-search.spec.js
@@ -61,58 +61,58 @@ describe("project text search", () => {
     dispatch(actions.addSearchQuery(mockQuery));
 
     expect(getTextSearchQuery(getState())).toEqual(mockQuery);
   });
 
   it("should search all the loaded sources based on the query", async () => {
     const { dispatch, getState } = createStore(threadClient);
     const mockQuery = "foo";
-    const csr1 = makeSource("foo1");
-    const csr2 = makeSource("foo2");
+    const source1 = makeSource("foo1");
+    const source2 = makeSource("foo2");
 
-    await dispatch(actions.newSource(csr1));
-    await dispatch(actions.newSource(csr2));
+    await dispatch(actions.newSource(source1));
+    await dispatch(actions.newSource(source2));
 
     await dispatch(actions.searchSources(mockQuery));
 
     const results = getTextSearchResults(getState());
     expect(results).toMatchSnapshot();
   });
 
   it("should ignore sources with minified versions", async () => {
-    const csr1 = makeSource("bar", { sourceMapURL: "bar:formatted" });
-    const csr2 = makeSource("bar:formatted");
+    const source1 = makeSource("bar", { sourceMapURL: "bar:formatted" });
+    const source2 = makeSource("bar:formatted");
 
     const mockMaps = {
       getOriginalSourceText: async () => ({
         source: "function bla(x, y) {\n const bar = 4; return 2;\n}",
         contentType: "text/javascript"
       }),
-      getOriginalURLs: async () => [csr2.source.url]
+      getOriginalURLs: async () => [source2.url]
     };
 
     const { dispatch, getState } = createStore(threadClient, {}, mockMaps);
     const mockQuery = "bla";
 
-    await dispatch(actions.newSource(csr1));
-    await dispatch(actions.newSource(csr2));
+    await dispatch(actions.newSource(source1));
+    await dispatch(actions.newSource(source2));
 
     await dispatch(actions.searchSources(mockQuery));
 
     const results = getTextSearchResults(getState());
     expect(results).toMatchSnapshot();
   });
 
   it("should search a specific source", async () => {
     const { dispatch, getState } = createStore(threadClient);
 
-    const csr = makeSource("bar");
-    await dispatch(actions.newSource(csr));
-    await dispatch(actions.loadSourceText(csr.source));
+    const source = makeSource("bar");
+    await dispatch(actions.newSource(source));
+    await dispatch(actions.loadSourceText(source));
 
     dispatch(actions.addSearchQuery("bla"));
 
     const barSource = getSource(getState(), "bar");
     if (!barSource) {
       throw new Error("no barSource");
     }
     const sourceId = barSource.id;
--- a/devtools/client/debugger/new/src/actions/tests/setProjectDirectoryRoot.spec.js
+++ b/devtools/client/debugger/new/src/actions/tests/setProjectDirectoryRoot.spec.js
@@ -8,17 +8,17 @@ import {
   createStore,
   selectors,
   actions,
   makeSource
 } from "../../utils/test-head";
 
 import type { Source } from "../../types";
 
-const { getProjectDirectoryRoot, getRelativeSources } = selectors;
+const { getProjectDirectoryRoot, getDisplayedSources } = selectors;
 
 describe("setProjectDirectoryRoot", () => {
   it("should set domain directory as root", async () => {
     const { dispatch, getState } = createStore();
     dispatch(actions.setProjectDirectoryRoot("example.com"));
     expect(getProjectDirectoryRoot(getState())).toBe("example.com");
   });
 
@@ -46,17 +46,17 @@ describe("setProjectDirectoryRoot", () =
   it("should filter sources", async () => {
     const store = createStore({});
     const { dispatch, getState } = store;
     await dispatch(actions.newSource(makeSource("js/scopes.js")));
     await dispatch(actions.newSource(makeSource("lib/vendor.js")));
 
     dispatch(actions.setProjectDirectoryRoot("localhost:8000/examples/js"));
 
-    const filteredSourcesByThread = getRelativeSources(getState());
+    const filteredSourcesByThread = getDisplayedSources(getState());
     const filteredSources = Object.values(filteredSourcesByThread)[0];
     const firstSource: Source = (Object.values(filteredSources)[0]: any);
 
     expect(firstSource.url).toEqual(
       "http://localhost:8000/examples/js/scopes.js"
     );
 
     expect(firstSource.relativeUrl).toEqual("scopes.js");
--- a/devtools/client/debugger/new/src/actions/tests/tabs.spec.js
+++ b/devtools/client/debugger/new/src/actions/tests/tabs.spec.js
@@ -13,74 +13,74 @@ import {
 const { getSelectedSource, getSourceTabs } = selectors;
 
 import { sourceThreadClient as threadClient } from "./helpers/threadClient.js";
 
 describe("closing tabs", () => {
   it("closing a tab", async () => {
     const { dispatch, getState } = createStore(threadClient);
 
-    const fooCSR = makeSource("foo.js");
-    await dispatch(actions.newSource(fooCSR));
+    const fooSource = makeSource("foo.js");
+    await dispatch(actions.newSource(fooSource));
     await dispatch(actions.selectLocation({ sourceId: "foo.js", line: 1 }));
-    dispatch(actions.closeTab(fooCSR.source));
+    dispatch(actions.closeTab(fooSource));
 
     expect(getSelectedSource(getState())).toBe(undefined);
     expect(getSourceTabs(getState())).toHaveLength(0);
   });
 
   it("closing the inactive tab", async () => {
     const { dispatch, getState } = createStore(threadClient);
 
-    const fooCSR = makeSource("foo.js");
-    await dispatch(actions.newSource(fooCSR));
+    const fooSource = makeSource("foo.js");
+    await dispatch(actions.newSource(fooSource));
     await dispatch(actions.newSource(makeSource("bar.js")));
     await dispatch(actions.selectLocation({ sourceId: "foo.js", line: 1 }));
     await dispatch(actions.selectLocation({ sourceId: "bar.js", line: 1 }));
-    dispatch(actions.closeTab(fooCSR.source));
+    dispatch(actions.closeTab(fooSource));
 
     const selected = getSelectedSource(getState());
     expect(selected && selected.id).toBe("bar.js");
     expect(getSourceTabs(getState())).toHaveLength(1);
   });
 
   it("closing the only tab", async () => {
     const { dispatch, getState } = createStore(threadClient);
 
-    const fooCSR = makeSource("foo.js");
-    await dispatch(actions.newSource(fooCSR));
+    const fooSource = makeSource("foo.js");
+    await dispatch(actions.newSource(fooSource));
     await dispatch(actions.selectLocation({ sourceId: "foo.js", line: 1 }));
-    dispatch(actions.closeTab(fooCSR.source));
+    dispatch(actions.closeTab(fooSource));
 
     expect(getSelectedSource(getState())).toBe(undefined);
     expect(getSourceTabs(getState())).toHaveLength(0);
   });
 
   it("closing the active tab", async () => {
     const { dispatch, getState } = createStore(threadClient);
 
-    const barCSR = makeSource("bar.js");
+    const barSource = makeSource("bar.js");
     await dispatch(actions.newSource(makeSource("foo.js")));
-    await dispatch(actions.newSource(barCSR));
+    await dispatch(actions.newSource(barSource));
     await dispatch(actions.selectLocation({ sourceId: "foo.js", line: 1 }));
     await dispatch(actions.selectLocation({ sourceId: "bar.js", line: 1 }));
-    await dispatch(actions.closeTab(barCSR.source));
+    await dispatch(actions.closeTab(barSource));
 
     const selected = getSelectedSource(getState());
     expect(selected && selected.id).toBe("foo.js");
     expect(getSourceTabs(getState())).toHaveLength(1);
   });
 
   it("closing many inactive tabs", async () => {
     const { dispatch, getState } = createStore(threadClient);
 
-    const fooCSR = makeSource("foo.js");
-    const barCSR = makeSource("bar.js");
-    await dispatch(actions.newSource(fooCSR));
-    await dispatch(actions.newSource(barCSR));
+    const fooSource = makeSource("foo.js");
+    const barSource = makeSource("bar.js");
+    await dispatch(actions.newSource(fooSource));
+    await dispatch(actions.newSource(barSource));
     await dispatch(actions.newSource(makeSource("bazz.js")));
     await dispatch(actions.selectLocation({ sourceId: "foo.js", line: 1 }));
     await dispatch(actions.selectLocation({ sourceId: "bar.js", line: 1 }));
     await dispatch(actions.selectLocation({ sourceId: "bazz.js", line: 1 }));
 
     const tabs = [
       "http://localhost:8000/examples/foo.js",
       "http://localhost:8000/examples/bar.js"
--- a/devtools/client/debugger/new/src/actions/tests/ui.spec.js
+++ b/devtools/client/debugger/new/src/actions/tests/ui.spec.js
@@ -12,17 +12,17 @@ import {
 } from "../../utils/test-head";
 
 const {
   getActiveSearch,
   getFrameworkGroupingState,
   getPaneCollapse,
   getHighlightedLineRange,
   getProjectDirectoryRoot,
-  getRelativeSources
+  getDisplayedSources
 } = selectors;
 
 import type { Source } from "../../types";
 
 describe("ui", () => {
   it("should toggle the visible state of project search", () => {
     const { dispatch, getState } = createStore();
     expect(getActiveSearch(getState())).toBe(null);
@@ -114,17 +114,17 @@ describe("setProjectDirectoryRoot", () =
   it("should filter sources", async () => {
     const store = createStore({});
     const { dispatch, getState } = store;
     await dispatch(actions.newSource(makeSource("js/scopes.js")));
     await dispatch(actions.newSource(makeSource("lib/vendor.js")));
 
     dispatch(actions.setProjectDirectoryRoot("localhost:8000/examples/js"));
 
-    const filteredSourcesByThread = getRelativeSources(getState());
+    const filteredSourcesByThread = getDisplayedSources(getState());
     const filteredSources = Object.values(filteredSourcesByThread)[0];
     const firstSource: Source = (Object.values(filteredSources)[0]: any);
 
     expect(firstSource.url).toEqual(
       "http://localhost:8000/examples/js/scopes.js"
     );
 
     expect(firstSource.relativeUrl).toEqual("scopes.js");
--- a/devtools/client/debugger/new/src/actions/types/ASTAction.js
+++ b/devtools/client/debugger/new/src/actions/types/ASTAction.js
@@ -1,33 +1,27 @@
 /* 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/>. */
 
 // @flow
 
 import type { SymbolDeclarations, AstLocation } from "../../workers/parser";
-import type { PausePoints, SourceMetaDataType } from "../../reducers/types";
+import type { SourceMetaDataType } from "../../reducers/types";
 import type { PromiseAction } from "../utils/middleware/promise";
 
 export type ASTAction =
   | PromiseAction<
       {|
         +type: "SET_SYMBOLS",
         +sourceId: string
       |},
       SymbolDeclarations
     >
   | {|
-      +type: "SET_PAUSE_POINTS",
-      +sourceText: string,
-      +sourceId: string,
-      +pausePoints: PausePoints
-    |}
-  | {|
       +type: "OUT_OF_SCOPE_LOCATIONS",
       +locations: ?(AstLocation[])
     |}
   | {|
       +type: "IN_SCOPE_LINES",
       +lines: AstLocation[]
     |}
   | PromiseAction<
--- a/devtools/client/debugger/new/src/actions/types/BreakpointAction.js
+++ b/devtools/client/debugger/new/src/actions/types/BreakpointAction.js
@@ -3,17 +3,17 @@
  * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
 
 // @flow
 
 import type {
   Breakpoint,
   SourceLocation,
   XHRBreakpoint,
-  BreakpointLinePositions
+  BreakpointPositions
 } from "../../types";
 
 import type { PromiseAction } from "../utils/middleware/promise";
 
 export type BreakpointAction =
   | PromiseAction<
       {|
         +type: "ADD_BREAKPOINT",
@@ -89,11 +89,11 @@ export type BreakpointAction =
       +breakpoints: Breakpoint[]
     |}
   | {|
       +type: "REMAP_BREAKPOINTS",
       +breakpoints: Breakpoint[]
     |}
   | {|
       type: "ADD_BREAKPOINT_POSITIONS",
-      positions: BreakpointLinePositions,
+      positions: BreakpointPositions,
       location: SourceLocation
     |};
--- a/devtools/client/debugger/new/src/actions/types/SourceAction.js
+++ b/devtools/client/debugger/new/src/actions/types/SourceAction.js
@@ -1,15 +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/>. */
 
 // @flow
 
-import type { Source, SourceActor, SourceLocation } from "../../types";
+import type { Source, SourceLocation } from "../../types";
 import type { PromiseAction } from "../utils/middleware/promise";
 
 export type LoadSourceAction = PromiseAction<
   {|
     +type: "LOAD_SOURCE_TEXT",
     +sourceId: string
   |},
   Source
@@ -17,18 +17,17 @@ export type LoadSourceAction = PromiseAc
 export type SourceAction =
   | LoadSourceAction
   | {|
       +type: "ADD_SOURCE",
       +source: Source
     |}
   | {|
       +type: "ADD_SOURCES",
-      +sources: Array<Source>,
-      +sourceActors: SourceActor[]
+      +sources: Array<Source>
     |}
   | {|
       +type: "UPDATE_SOURCE",
       +source: Source
     |}
   | {|
       +type: "SET_SELECTED_LOCATION",
       +source: Source,
--- a/devtools/client/debugger/new/src/client/README.md
+++ b/devtools/client/debugger/new/src/client/README.md
@@ -33,17 +33,17 @@ The [Remote Debugger Protocol][protocol]
 
 When the client wants to add a breakpoint, it avoids race conditions by doing
 temporary pauses called interrupts.
 
 We want to do these interrupts transparently, so we've decided that the client
 should not notify the application that the thread has been paused or resumed.
 
 [protocol]: https://searchfox.org/mozilla-central/source/devtools/docs/backend/protocol.md
-[dt-connect]: https://github.com/devtools-html/devtools-core/tree/master/packages/devtools-connection
+[dt-connect]: https://github.com/firefox-devtools/devtools-core/tree/master/packages/devtools-connection
 [devtools-client.js]: https://searchfox.org/mozilla-central/source/devtools/shared/client/debugger-client.js
 
 ## Chrome
 
 ### Chrome Debugger Protocol
 
 The chrome debugger protocol is available [here][devtools-protocol-viewer]. And
 is maintained in the devtools-protocol [repo][devtools-protocol-gh].
--- a/devtools/client/debugger/new/src/client/chrome/commands.js
+++ b/devtools/client/debugger/new/src/client/chrome/commands.js
@@ -109,18 +109,16 @@ function debuggeeCommand(script: string)
 }
 
 function navigate(url: string) {
   return pageAgent.navigate({ url });
 }
 
 function getBreakpointByLocation(location: SourceLocation) {}
 
-function setPausePoints() {}
-
 function getFrameScopes() {}
 function evaluateInFrame() {}
 function evaluateExpressions() {}
 
 const clientCommands = {
   resume,
   stepIn,
   stepOut,
@@ -130,15 +128,14 @@ const clientCommands = {
   sourceContents,
   setBreakpoint,
   removeBreakpoint,
   evaluate,
   debuggeeCommand,
   navigate,
   getProperties,
   getBreakpointByLocation,
-  setPausePoints,
   getFrameScopes,
   evaluateInFrame,
   evaluateExpressions
 };
 
 export { setupCommands, clientCommands };
--- a/devtools/client/debugger/new/src/client/firefox/commands.js
+++ b/devtools/client/debugger/new/src/client/firefox/commands.js
@@ -13,31 +13,29 @@ import type {
   BreakpointLocation,
   BreakpointOptions,
   EventListenerBreakpoints,
   Frame,
   FrameId,
   Script,
   SourceId,
   SourceActor,
-  SourceActorLocation,
-  Worker
+  Worker,
+  Range
 } from "../../types";
 
 import type {
   TabTarget,
   DebuggerClient,
   Grip,
   ThreadClient,
   ObjectClient,
   SourcesPacket
 } from "./types";
 
-import type { PausePointsMap } from "../../workers/parser";
-
 let workerClients: Object;
 let threadClient: ThreadClient;
 let tabTarget: TabTarget;
 let debuggerClient: DebuggerClient;
 let sourceActors: { [ActorId]: SourceId };
 let breakpoints: { [string]: Object };
 let supportsWasm: boolean;
 
@@ -290,27 +288,16 @@ async function blackBox(
   const sourceClient = threadClient.source({ actor: sourceActor.actor });
   if (isBlackBoxed) {
     await sourceClient.unblackBox(range);
   } else {
     await sourceClient.blackBox(range);
   }
 }
 
-async function setPausePoints(
-  sourceActor: SourceActor,
-  pausePoints: PausePointsMap
-) {
-  return sendPacket({
-    to: sourceActor.actor,
-    type: "setPausePoints",
-    pausePoints
-  });
-}
-
 async function setSkipPausing(thread: string, shouldSkip: boolean) {
   const client = lookupThreadClient(thread);
   return client.request({
     skip: shouldSkip,
     to: client.actor,
     type: "skipBreakpoints"
   });
 }
@@ -399,30 +386,26 @@ async function fetchWorkers(): Promise<W
   return workers;
 }
 
 function getMainThread() {
   return threadClient.actor;
 }
 
 async function getBreakpointPositions(
-  location: SourceActorLocation
-): Promise<Array<Number>> {
-  const {
-    sourceActor: { thread, actor },
-    line
-  } = location;
+  sourceActor: SourceActor,
+  range: ?Range
+): Promise<{ [string]: number[] }> {
+  const { thread, actor } = sourceActor;
   const sourceThreadClient = lookupThreadClient(thread);
   const sourceClient = sourceThreadClient.source({ actor });
-  const { positions } = await sourceClient.getBreakpointPositionsCompressed({
-    start: { line },
-    end: { line }
-  });
-
-  return positions ? positions[line] : [];
+  const { positions } = await sourceClient.getBreakpointPositionsCompressed(
+    range
+  );
+  return positions;
 }
 
 const clientCommands = {
   autocomplete,
   blackBox,
   createObjectClient,
   releaseActor,
   interrupt,
@@ -452,14 +435,13 @@ const clientCommands = {
   getProperties,
   getFrameScopes,
   pauseOnExceptions,
   fetchSources,
   registerSourceActor,
   fetchWorkers,
   getMainThread,
   sendPacket,
-  setPausePoints,
   setSkipPausing,
   setEventListenerBreakpoints
 };
 
 export { setupCommands, clientCommands };
--- a/devtools/client/debugger/new/src/client/firefox/create.js
+++ b/devtools/client/debugger/new/src/client/firefox/create.js
@@ -5,27 +5,26 @@
 // @flow
 // This module converts Firefox specific types to the generic types
 
 import type { Frame, Source, ThreadId } from "../../types";
 import type {
   PausedPacket,
   FramesResponse,
   FramePacket,
-  SourcePayload,
-  CreateSourceResult
+  SourcePayload
 } from "./types";
 
 import { clientCommands } from "./commands";
 
 export function createFrame(thread: ThreadId, frame: FramePacket): ?Frame {
   if (!frame) {
     return null;
   }
-  
+
   const location = {
     sourceId: clientCommands.getSourceForActor(frame.where.actor),
     line: frame.where.line,
     column: frame.where.column
   };
 
   return {
     id: frame.actor,
@@ -42,35 +41,37 @@ export function createFrame(thread: Thre
 function makeSourceId(source) {
   return source.url ? `sourceURL-${source.url}` : `source-${source.actor}`;
 }
 
 export function createSource(
   thread: string,
   source: SourcePayload,
   { supportsWasm }: { supportsWasm: boolean }
-): CreateSourceResult {
+): Source {
+  const id = makeSourceId(source);
+  const sourceActor = {
+    actor: source.actor,
+    source: id,
+    thread
+  };
   const createdSource: any = {
-    id: makeSourceId(source),
+    id,
     url: source.url,
     relativeUrl: source.url,
     isPrettyPrinted: false,
     sourceMapURL: source.sourceMapURL,
     introductionUrl: source.introductionUrl,
     isBlackBoxed: false,
     loadedState: "unloaded",
-    isWasm: supportsWasm && source.introductionType === "wasm"
-  };
-  const sourceActor = {
-    actor: source.actor,
-    source: createdSource.id,
-    thread
+    isWasm: supportsWasm && source.introductionType === "wasm",
+    actors: [sourceActor]
   };
   clientCommands.registerSourceActor(sourceActor);
-  return { sourceActor, source: (createdSource: Source) };
+  return createdSource;
 }
 
 export function createPause(
   thread: string,
   packet: PausedPacket,
   response: FramesResponse
 ): any {
   // NOTE: useful when the debugger is already paused
--- a/devtools/client/debugger/new/src/client/firefox/types.js
+++ b/devtools/client/debugger/new/src/client/firefox/types.js
@@ -16,17 +16,17 @@ import type {
   FrameId,
   ActorId,
   Script,
   Source,
   Pause,
   Frame,
   SourceId,
   Worker,
-  SourceActor
+  Range
 } from "../../types";
 
 type URL = string;
 
 /**
  * The protocol is carried by a reliable, bi-directional byte stream; data sent
  * in both directions consists of JSON objects, called packets. A packet is a
  * top-level JSON object, not contained inside any other value.
@@ -66,17 +66,17 @@ type URL = string;
 /**
  * Frame Packet
  * @memberof firefox/packets
  * @static
  */
 export type FramePacket = {
   actor: ActorId,
   arguments: any[],
-  callee: any,
+  displayName: string,
   environment: any,
   this: any,
   depth?: number,
   oldest?: boolean,
   type: "pause" | "call",
   where: {| actor: string, line: number, column: number |}
 };
 
@@ -115,21 +115,16 @@ export type SourcePacket = {
  * @memberof firefox/packets
  * @static
  */
 export type SourcesPacket = {
   from: ActorId,
   sources: SourcePayload[]
 };
 
-export type CreateSourceResult = {|
-  sourceActor?: SourceActor,
-  +source: Source
-|};
-
 /**
  * Pause Packet sent when the server is in a "paused" state
  *
  * @memberof firefox
  * @static
  */
 export type PausedPacket = {
   actor: ActorId,
@@ -309,20 +304,17 @@ export type FunctionGrip = {|
  * SourceClient
  * @memberof firefox
  * @static
  */
 export type SourceClient = {
   source: () => { source: any, contentType?: string },
   _activeThread: ThreadClient,
   actor: string,
-  getBreakpointPositionsCompressed: (range: {
-    start: { line: number },
-    end: { line: number }
-  }) => Promise<any>,
+  getBreakpointPositionsCompressed: (range: ?Range) => Promise<any>,
   prettyPrint: number => Promise<*>,
   disablePrettyPrint: () => Promise<*>,
   blackBox: (range?: Range) => Promise<*>,
   unblackBox: (range?: Range) => Promise<*>
 };
 
 /**
  * ObjectClient
--- a/devtools/client/debugger/new/src/components/Editor/ColumnBreakpoint.js
+++ b/devtools/client/debugger/new/src/components/Editor/ColumnBreakpoint.js
@@ -27,21 +27,20 @@ type Props = {
   breakpointActions: BreakpointItemActions
 };
 
 const breakpointImg = document.createElement("button");
 ReactDOM.render(<Svg name={"column-marker"} />, breakpointImg);
 
 function makeBookmark({ breakpoint }, { onClick, onContextMenu }) {
   const bp = breakpointImg.cloneNode(true);
-  if (!breakpoint) {
-    return;
-  }
-  const { condition, logValue } = breakpoint.options;
+
   const isActive = breakpoint && !breakpoint.disabled;
+  const condition = breakpoint && breakpoint.options.condition;
+  const logValue = breakpoint && breakpoint.options.logValue;
 
   bp.className = classnames("column-breakpoint", {
     "has-condition": condition,
     "has-log": logValue,
     active: isActive,
     disabled: !isActive
   });
 
--- a/devtools/client/debugger/new/src/components/Editor/ColumnBreakpoints.css
+++ b/devtools/client/debugger/new/src/components/Editor/ColumnBreakpoints.css
@@ -1,27 +1,27 @@
 /* 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/>. */
 
 .column-breakpoint {
   display: inline;
-  padding: 0;
-  padding-inline-end: 4px;
+  padding-inline-start: 1px;
+  padding-inline-end: 3px;
 }
 
 .column-breakpoint:hover {
   background-color: transparent;
 }
 
 .column-breakpoint svg {
-  display: inline;
+  display: inline-block;
   cursor: pointer;
-  height: 12px;
-  width: 9px;
+  height: 13px;
+  width: 11px;
   vertical-align: top;
 }
 
 .column-breakpoint.active svg {
   fill: var(--blue-50);
   stroke: var(--blue-60);
 }
 
--- a/devtools/client/debugger/new/src/components/Editor/Editor.css
+++ b/devtools/client/debugger/new/src/components/Editor/Editor.css
@@ -35,17 +35,17 @@
 }
 
 .theme-light {
   --theme-conditional-breakpoint-color: var(--theme-body-color);
 }
 
 /**
  * There's a known codemirror flex issue with chrome that this addresses.
- * BUG https://github.com/devtools-html/debugger.html/issues/63
+ * BUG https://github.com/firefox-devtools/debugger.html/issues/63
  */
 .editor-wrapper {
   position: absolute;
   height: calc(100% - var(--editor-header-height));
   width: calc(100% - 1px);
   top: var(--editor-header-height);
   left: 0px;
 }
@@ -73,45 +73,35 @@ html[dir="rtl"] .editor-mount {
 .theme-light .cm-s-mozilla .empty-line .CodeMirror-linenumber {
   color: var(--grey-40);
 }
 
 .theme-dark .cm-s-mozilla .empty-line .CodeMirror-linenumber {
   color: var(--grey-50);
 }
 
-:not(.empty-line):not(.new-breakpoint)
-  > .CodeMirror-gutter-wrapper:hover
-  > .CodeMirror-linenumber {
-  height: 13px;
-  color: var(--theme-body-color);
-  /* Add 1px offset to the background to match it
-    with the actual breakpoint image dimensions */
-  background: linear-gradient(
-    to bottom,
-    transparent 1px,
-    var(--gutter-hover-background-color) 0
-  );
-}
-
 .new-breakpoint .CodeMirror-linenumber {
   pointer-events: none;
 }
 
 :not(.empty-line):not(.new-breakpoint)
   > .CodeMirror-gutter-wrapper:hover
   > .CodeMirror-linenumber::after {
   content: "";
   position: absolute;
-  top: 1px;
-  height: 12px;
-  width: 9px;
+  /* paint below the number */
+  z-index: -1;
+  top: 0;
+  left: 0;
+  right: -7px;
+  bottom: 0;
+  height: 15px;
   background-color: var(--gutter-hover-background-color);
   mask: url(/images/breakpoint.svg) no-repeat;
-  mask-size: auto 12px;
+  mask-size: auto 15px;
   mask-position: right;
 }
 
 .editor-wrapper .breakpoints {
   position: absolute;
   top: 0;
   left: 0;
 }
@@ -121,28 +111,28 @@ html[dir="rtl"] .editor-mount {
   overflow: hidden;
 }
 
 .function-search .results {
   height: auto;
 }
 
 .editor.hit-marker {
-  height: 14px;
+  height: 15px;
 }
 
 .editor-wrapper .highlight-lines {
   background: var(--theme-selection-background-hover);
 }
 
 .editor.new-breakpoint svg {
   fill: var(--breakpoint-fill);
   stroke: var(--breakpoint-stroke);
   width: 60px;
-  height: 14px;
+  height: 15px;
   position: absolute;
   top: 0px;
   right: -4px;
 }
 
 .inline-bp {
   background-color: #9ddfff;
   width: 20px;
@@ -177,36 +167,33 @@ html[dir="rtl"] .editor-mount {
   stroke: var(--breakpoint-stroke-disabled);
   fill-opacity: 0.5;
 }
 
 .editor.column-breakpoint svg {
   fill: var(--theme-selection-background);
   vertical-align: middle;
   width: 17px;
-  height: 14px;
+  height: 15px;
 }
 
 .editor.column-breakpoint.breakpoint-disabled svg {
   opacity: 0.3;
 }
 
 .CodeMirror {
   width: 100%;
   height: 100%;
 }
 
 .editor-wrapper .editor-mount {
   width: 100%;
   background-color: var(--theme-body-background);
-}
-
-.CodeMirror-linenumber {
-  font-size: 11px;
-  line-height: 14px;
+  font-size: var(--theme-code-font-size);
+  line-height: var(--theme-code-line-height);
 }
 
 .folding-enabled .CodeMirror-linenumber {
   text-align: left;
   padding: 0 0 0 2px;
 }
 
 /* set the linenumber white when there is a breakpoint */
@@ -217,20 +204,16 @@ html[dir="rtl"] .editor-mount {
   color: white;
 }
 
 /* move the breakpoint below the other gutter elements */
 .new-breakpoint .CodeMirror-gutter-elt:nth-child(2) {
   z-index: 0;
 }
 
-.editor-wrapper .CodeMirror-line {
-  font-size: 11px;
-}
-
 .theme-dark .editor-wrapper .CodeMirror-line .cm-comment {
   color: var(--theme-comment);
 }
 
 .debug-expression,
 .new-debug-line .column-breakpoint {
   background-color: var(--debug-expression-background);
 }
--- a/devtools/client/debugger/new/src/components/Editor/Footer.css
+++ b/devtools/client/debugger/new/src/components/Editor/Footer.css
@@ -53,17 +53,17 @@
 
 .source-footer > .commands > div.loader {
   vertical-align: top;
   width: 20px;
   margin: 0 4px;
 }
 
 .source-footer > .commands > .blackboxed > .img.blackBox {
-  background-color: var(--theme-highlight-blue);
+  background-color: var(--theme-icon-checked-color);
 }
 
 .source-footer .blackbox-summary,
 .source-footer .mapped-source,
 .source-footer .cursor-position {
   color: var(--theme-body-color);
   padding-right: 2.5px;
 }
--- a/devtools/client/debugger/new/src/components/Editor/Tab.js
+++ b/devtools/client/debugger/new/src/components/Editor/Tab.js
@@ -18,17 +18,18 @@ import type { Source } from "../../types
 import actions from "../../actions";
 
 import {
   getDisplayPath,
   getFileURL,
   getRawSourceURL,
   getSourceQueryString,
   getTruncatedFileName,
-  isPretty
+  isPretty,
+  shouldBlackbox
 } from "../../utils/source";
 import { shouldShowPrettyPrint } from "../../utils/editor";
 import { copyToTheClipboard } from "../../utils/clipboard";
 import { getTabMenuItems } from "../../utils/tabs";
 
 import {
   getSelectedSource,
   getActiveSearch,
@@ -46,31 +47,33 @@ type Props = {
   selectedSource: Source,
   source: Source,
   activeSearch: ActiveSearchType,
   hasSiblingOfSameName: boolean,
   selectSource: typeof actions.selectSource,
   closeTab: typeof actions.closeTab,
   closeTabs: typeof actions.closeTabs,
   togglePrettyPrint: typeof actions.togglePrettyPrint,
-  showSource: typeof actions.showSource
+  showSource: typeof actions.showSource,
+  toggleBlackBox: typeof actions.toggleBlackBox
 };
 
 class Tab extends PureComponent<Props> {
   onTabContextMenu = (event, tab: string) => {
     event.preventDefault();
     this.showContextMenu(event, tab);
   };
 
   showContextMenu(e, tab: string) {
     const {
       closeTab,
       closeTabs,
       tabSources,
       showSource,
+      toggleBlackBox,
       togglePrettyPrint,
       selectedSource,
       source
     } = this.props;
 
     const tabCount = tabSources.length;
     const otherTabs = tabSources.filter(t => t.id !== tab);
     const sourceTab = tabSources.find(t => t.id == tab);
@@ -130,23 +133,35 @@ class Tab extends PureComponent<Props> {
         item: {
           ...tabMenuItems.showSource,
           disabled: !selectedSource.url,
           click: () => showSource(tab)
         }
       }
     ];
 
-    items.push({
-      item: {
-        ...tabMenuItems.prettyPrint,
-        click: () => togglePrettyPrint(tab),
-        disabled: !shouldShowPrettyPrint(source)
+    items.push(
+      {
+        item: {
+          ...tabMenuItems.toggleBlackBox,
+          label: source.isBlackBoxed
+            ? L10N.getStr("sourceFooter.unblackbox")
+            : L10N.getStr("sourceFooter.blackbox"),
+          disabled: !shouldBlackbox(source),
+          click: () => toggleBlackBox(source)
+        }
+      },
+      {
+        item: {
+          ...tabMenuItems.prettyPrint,
+          click: () => togglePrettyPrint(tab),
+          disabled: !shouldShowPrettyPrint(source)
+        }
       }
-    });
+    );
 
     showMenu(e, buildMenu(items));
   }
 
   isProjectSearchEnabled() {
     return this.props.activeSearch === "project";
   }
 
@@ -229,11 +244,12 @@ const mapStateToProps = (state, { source
 
 export default connect(
   mapStateToProps,
   {
     selectSource: actions.selectSource,
     closeTab: actions.closeTab,
     closeTabs: actions.closeTabs,
     togglePrettyPrint: actions.togglePrettyPrint,
-    showSource: actions.showSource
+    showSource: actions.showSource,
+    toggleBlackBox: actions.toggleBlackBox
   }
 )(Tab);
--- a/devtools/client/debugger/new/src/components/Editor/Tabs.css
+++ b/devtools/client/debugger/new/src/components/Editor/Tabs.css
@@ -3,17 +3,16 @@
  * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
 
 .source-header {
   display: flex;
   width: 100%;
   height: var(--editor-header-height);
   border-bottom: 1px solid var(--theme-splitter-color);
   background-color: var(--theme-toolbar-background);
-  --overflow-button-width: 28px;
 }
 
 .source-header * {
   -moz-user-select: none;
   user-select: none;
 }
 
 .source-header .command-bar {
--- a/devtools/client/debugger/new/src/components/Editor/tests/DebugLine.spec.js
+++ b/devtools/client/debugger/new/src/components/Editor/tests/DebugLine.spec.js
@@ -26,17 +26,17 @@ function createMockDocument(clear) {
 
 function generateDefaults(editor, overrides) {
   return {
     editor,
     pauseInfo: {
       why: { type: "breakpoint" }
     },
     frame: null,
-    source: makeSource("foo").source,
+    source: makeSource("foo"),
     ...overrides
   };
 }
 
 function createFrame(line) {
   return {
     location: {
       sourceId: "foo",
@@ -60,33 +60,33 @@ function render(overrides = {}) {
   });
   return { component, props, clear, editor, doc };
 }
 
 describe("DebugLine Component", () => {
   describe("pausing at the first location", () => {
     it("should show a new debug line", async () => {
       const { component, props, doc } = render({
-        source: makeSource("foo", { loadedState: "loaded" }).source
+        source: makeSource("foo", { loadedState: "loaded" })
       });
       const line = 2;
       const frame = createFrame(line);
 
       component.setProps({ ...props, frame });
 
       expect(doc.removeLineClass.mock.calls).toEqual([]);
       expect(doc.addLineClass.mock.calls).toEqual([
         [toEditorLine("foo", line), "line", "new-debug-line"]
       ]);
     });
 
     describe("pausing at a new location", () => {
       it("should replace the first debug line", async () => {
         const { props, component, clear, doc } = render({
-          source: makeSource("foo", { loadedState: "loaded" }).source
+          source: makeSource("foo", { loadedState: "loaded" })
         });
 
         component.instance().debugExpression = { clear: jest.fn() };
         const firstLine = 2;
         const secondLine = 2;
 
         component.setProps({ ...props, frame: createFrame(firstLine) });
         component.setProps({
--- a/devtools/client/debugger/new/src/components/Editor/tests/Footer.spec.js
+++ b/devtools/client/debugger/new/src/components/Editor/tests/Footer.spec.js
@@ -24,17 +24,17 @@ function generateDefaults(overrides) {
     editor: {
       codeMirror: {
         doc: {},
         cursorActivity: jest.fn(),
         on: jest.fn()
       }
     },
     endPanelCollapsed: false,
-    selectedSource: makeSource("foo").source,
+    selectedSource: makeSource("foo"),
     ...overrides
   };
 }
 
 function render(overrides = {}, position = { line: 0, column: 0 }) {
   const clear = jest.fn();
   const props = generateDefaults(overrides);
 
--- a/devtools/client/debugger/new/src/components/PrimaryPanes/OutlineFilter.js
+++ b/devtools/client/debugger/new/src/components/PrimaryPanes/OutlineFilter.js
@@ -32,17 +32,17 @@ export default class OutlineFilter exten
   onKeyDown = (e: SyntheticKeyboardEvent<HTMLInputElement>) => {
     if (e.key === "Escape" && this.props.filter !== "") {
       // use preventDefault to override toggling the split-console which is
       // also bound to the ESC key
       e.preventDefault();
       this.props.updateFilter("");
     } else if (e.key === "Enter") {
       // We must prevent the form submission from taking any action
-      // https://github.com/devtools-html/debugger.html/pull/7308
+      // https://github.com/firefox-devtools/debugger.html/pull/7308
       e.preventDefault();
     }
   };
 
   render() {
     const { focused } = this.state;
     return (
       <div className="outline-filter">
--- a/devtools/client/debugger/new/src/components/PrimaryPanes/SourcesTree.js
+++ b/devtools/client/debugger/new/src/components/PrimaryPanes/SourcesTree.js
@@ -11,17 +11,17 @@ import { connect } from "../../utils/con
 
 // Selectors
 import {
   getShownSource,
   getSelectedSource,
   getDebuggeeUrl,
   getExpandedState,
   getProjectDirectoryRoot,
-  getRelativeSourcesForThread,
+  getDisplayedSourcesForThread,
   getFocusedSourceItem,
   getWorkerByThread,
   getWorkerCount
 } from "../../selectors";
 
 import { getGeneratedSourceByURL } from "../../reducers/sources";
 
 // Actions
@@ -339,53 +339,53 @@ class SourcesTree extends Component<Prop
         {this.renderTree()}
       </div>
     );
   }
 }
 
 function getSourceForTree(
   state: AppState,
-  relativeSources: SourcesMap,
+  displayedSources: SourcesMap,
   source: ?Source,
   thread
 ): ?Source {
   if (!source) {
     return null;
   }
 
-  source = relativeSources[source.id];
+  source = displayedSources[source.id];
   if (!source || !source.isPrettyPrinted) {
     return source;
   }
 
   return getGeneratedSourceByURL(state, getRawSourceURL(source.url));
 }
 
 const mapStateToProps = (state, props) => {
   const selectedSource = getSelectedSource(state);
   const shownSource = getShownSource(state);
   const focused = getFocusedSourceItem(state);
   const thread = props.thread;
-  const relativeSources = getRelativeSourcesForThread(state, thread);
+  const displayedSources = getDisplayedSourcesForThread(state, thread);
 
   return {
-    shownSource: getSourceForTree(state, relativeSources, shownSource, thread),
+    shownSource: getSourceForTree(state, displayedSources, shownSource, thread),
     selectedSource: getSourceForTree(
       state,
-      relativeSources,
+      displayedSources,
       selectedSource,
       thread
     ),
     debuggeeUrl: getDebuggeeUrl(state),
     expanded: getExpandedState(state, props.thread),
     focused: focused && focused.thread == props.thread ? focused.item : null,
     projectRoot: getProjectDirectoryRoot(state),
-    sources: relativeSources,
-    sourceCount: Object.values(relativeSources).length,
+    sources: displayedSources,
+    sourceCount: Object.values(displayedSources).length,
     worker: getWorkerByThread(state, thread),
     workerCount: getWorkerCount(state)
   };
 };
 
 export default connect(
   mapStateToProps,
   {
--- a/devtools/client/debugger/new/src/components/PrimaryPanes/SourcesTreeItem.js
+++ b/devtools/client/debugger/new/src/components/PrimaryPanes/SourcesTreeItem.js
@@ -17,17 +17,18 @@ import {
   getHasSiblingOfSameName,
   hasPrettySource as checkHasPrettySource
 } from "../../selectors";
 import actions from "../../actions";
 
 import {
   isOriginal as isOriginalSource,
   getSourceQueryString,
-  isUrlExtension
+  isUrlExtension,
+  shouldBlackbox
 } from "../../utils/source";
 import { isDirectory } from "../../utils/sources-tree";
 import { copyToTheClipboard } from "../../utils/clipboard";
 import { features } from "../../utils/prefs";
 
 import type { TreeNode } from "../../utils/sources-tree/types";
 import type { Source } from "../../types";
 
@@ -41,17 +42,18 @@ type Props = {
   expanded: boolean,
   hasMatchingGeneratedSource: boolean,
   hasSiblingOfSameName: boolean,
   hasPrettySource: boolean,
   focusItem: TreeNode => void,
   selectItem: TreeNode => void,
   setExpanded: (TreeNode, boolean, boolean) => void,
   clearProjectDirectoryRoot: typeof actions.clearProjectDirectoryRoot,
-  setProjectDirectoryRoot: typeof actions.setProjectDirectoryRoot
+  setProjectDirectoryRoot: typeof actions.setProjectDirectoryRoot,
+  toggleBlackBox: typeof actions.toggleBlackBox
 };
 
 type State = {};
 
 type MenuOption = {
   id: string,
   label: string,
   disabled: boolean,
@@ -127,17 +129,29 @@ class SourceTreeItem extends Component<P
         const copySourceUri2 = {
           id: "node-menu-copy-source",
           label: copySourceUri2Label,
           accesskey: copySourceUri2Key,
           disabled: false,
           click: () => copyToTheClipboard(contents.url)
         };
 
-        menuOptions.push(copySourceUri2);
+        const { source } = this.props;
+        if (source) {
+          const blackBoxMenuItem = {
+            id: "node-menu-blackbox",
+            label: source.isBlackBoxed
+              ? L10N.getStr("sourceFooter.unblackbox")
+              : L10N.getStr("sourceFooter.blackbox"),
+            accesskey: L10N.getStr("sourceFooter.blackbox.accesskey"),
+            disabled: !shouldBlackbox(source),
+            click: () => this.props.toggleBlackBox(source)
+          };
+          menuOptions.push(copySourceUri2, blackBoxMenuItem);
+        }
       }
     }
 
     if (isDirectory(item)) {
       this.addCollapseExpandAllOptions(menuOptions, item);
 
       if (features.root) {
         const { path } = item;
@@ -264,11 +278,12 @@ const mapStateToProps = (state, props) =
     hasPrettySource: source ? checkHasPrettySource(state, source.id) : false
   };
 };
 
 export default connect(
   mapStateToProps,
   {
     setProjectDirectoryRoot: actions.setProjectDirectoryRoot,
-    clearProjectDirectoryRoot: actions.clearProjectDirectoryRoot
+    clearProjectDirectoryRoot: actions.clearProjectDirectoryRoot,
+    toggleBlackBox: actions.toggleBlackBox
   }
 )(SourceTreeItem);
--- a/devtools/client/debugger/new/src/components/PrimaryPanes/index.js
+++ b/devtools/client/debugger/new/src/components/PrimaryPanes/index.js
@@ -5,17 +5,17 @@
 // @flow
 
 import React, { Component } from "react";
 import classnames from "classnames";
 import { Tab, Tabs, TabList, TabPanels } from "react-aria-components/src/tabs";
 
 import actions from "../../actions";
 import {
-  getRelativeSources,
+  getDisplayedSources,
   getActiveSearch,
   getProjectDirectoryRoot,
   getSelectedPrimaryPaneTab,
   getThreads
 } from "../../selectors";
 import { features, prefs } from "../../utils/prefs";
 import { connect } from "../../utils/connect";
 import { formatKeyShortcut } from "../../utils/text";
@@ -160,17 +160,17 @@ class PrimaryPanes extends Component<Pro
         </TabPanels>
       </Tabs>
     );
   }
 }
 
 const mapStateToProps = state => ({
   selectedTab: getSelectedPrimaryPaneTab(state),
-  sources: getRelativeSources(state),
+  sources: getDisplayedSources(state),
   sourceSearchOn: getActiveSearch(state) === "source",
   threads: getThreads(state),
   projectRoot: getProjectDirectoryRoot(state)
 });
 
 const connector = connect(
   mapStateToProps,
   {
--- a/devtools/client/debugger/new/src/components/PrimaryPanes/tests/SourcesTree.spec.js
+++ b/devtools/client/debugger/new/src/components/PrimaryPanes/tests/SourcesTree.spec.js
@@ -4,17 +4,17 @@
 
 // @flow
 
 import React from "react";
 import { shallow } from "enzyme";
 import { showMenu } from "devtools-contextmenu";
 
 import SourcesTree from "../SourcesTree";
-import { createSource } from "../../../reducers/sources";
+import { makeMockSource } from "../../../utils/test-mockup";
 import { copyToTheClipboard } from "../../../utils/clipboard";
 
 jest.mock("devtools-contextmenu", () => ({ showMenu: jest.fn() }));
 jest.mock("../../../utils/clipboard", () => ({
   copyToTheClipboard: jest.fn()
 }));
 
 describe("SourcesTree", () => {
@@ -394,26 +394,21 @@ function render(overrides = {}) {
 
 function createMockSource(
   id,
   url,
   isBlackBoxed = false,
   sourceMapURL = null,
   thread = ""
 ) {
-  return createSource({
-    id: id,
-    thread,
-    url: url,
-    isPrettyPrinted: false,
-    isWasm: false,
-    sourceMapURL,
-    isBlackBoxed: isBlackBoxed,
-    loadedState: "unloaded"
-  });
+  return {
+    ...makeMockSource(url, id),
+    isBlackBoxed,
+    sourceMapURL
+  };
 }
 
 function createMockDirectory(path = "folder/", name = "folder", contents = []) {
   return {
     type: "directory",
     name,
     path,
     contents
--- a/devtools/client/debugger/new/src/components/PrimaryPanes/tests/SourcesTreeItem.spec.js
+++ b/devtools/client/debugger/new/src/components/PrimaryPanes/tests/SourcesTreeItem.spec.js
@@ -4,17 +4,17 @@
 
 // @flow
 
 import React from "react";
 import { shallow } from "enzyme";
 import { showMenu } from "devtools-contextmenu";
 
 import SourcesTreeItem from "../SourcesTreeItem";
-import { createSource } from "../../../reducers/sources";
+import { makeMockSource } from "../../../utils/test-mockup";
 import { copyToTheClipboard } from "../../../utils/clipboard";
 
 jest.mock("devtools-contextmenu", () => ({ showMenu: jest.fn() }));
 jest.mock("../../../utils/clipboard", () => ({
   copyToTheClipboard: jest.fn()
 }));
 
 describe("SourceTreeItem", () => {
@@ -78,40 +78,86 @@ describe("SourceTreeItem", () => {
     it("shows context menu on file to copy source uri", async () => {
       const menuOptions = [
         {
           accesskey: "u",
           click: expect.any(Function),
           disabled: false,
           id: "node-menu-copy-source",
           label: "Copy source URI"
+        },
+        {
+          accesskey: "B",
+          click: expect.any(Function),
+          disabled: true,
+          id: "node-menu-blackbox",
+          label: "Blackbox source"
         }
       ];
       const mockEvent = {
         preventDefault: jest.fn(),
         stopPropagation: jest.fn()
       };
       const { props, instance } = render({
         projectRoot: "root/"
       });
-      const { item } = instance.props;
+      const { item, source } = instance.props;
 
-      await instance.onContextMenu(mockEvent, item);
+      await instance.onContextMenu(mockEvent, item, source);
 
       expect(showMenu).toHaveBeenCalledWith(mockEvent, menuOptions);
 
       expect(mockEvent.preventDefault).toHaveBeenCalled();
       expect(mockEvent.stopPropagation).toHaveBeenCalled();
 
       showMenu.mock.calls[0][1][0].click();
       expect(props.setProjectDirectoryRoot).not.toHaveBeenCalled();
       expect(props.clearProjectDirectoryRoot).not.toHaveBeenCalled();
       expect(copyToTheClipboard).toHaveBeenCalled();
     });
 
+    it("shows context menu on file to blackbox source", async () => {
+      const menuOptions = [
+        {
+          accesskey: "u",
+          click: expect.any(Function),
+          disabled: false,
+          id: "node-menu-copy-source",
+          label: "Copy source URI"
+        },
+        {
+          accesskey: "B",
+          click: expect.any(Function),
+          disabled: true,
+          id: "node-menu-blackbox",
+          label: "Blackbox source"
+        }
+      ];
+      const mockEvent = {
+        preventDefault: jest.fn(),
+        stopPropagation: jest.fn()
+      };
+      const { props, instance } = render({
+        projectRoot: "root/"
+      });
+      const { item, source } = instance.props;
+
+      await instance.onContextMenu(mockEvent, item, source);
+
+      expect(showMenu).toHaveBeenCalledWith(mockEvent, menuOptions);
+
+      expect(mockEvent.preventDefault).toHaveBeenCalled();
+      expect(mockEvent.stopPropagation).toHaveBeenCalled();
+
+      showMenu.mock.calls[0][1][1].click();
+      expect(props.setProjectDirectoryRoot).not.toHaveBeenCalled();
+      expect(props.clearProjectDirectoryRoot).not.toHaveBeenCalled();
+      expect(props.toggleBlackBox).toHaveBeenCalled();
+    });
+
     it("shows context menu on root to remove directory root", async () => {
       const menuOptions = [
         {
           click: expect.any(Function),
           disabled: false,
           id: "node-menu-collapse-all",
           label: "Collapse all"
         },
@@ -290,35 +336,36 @@ describe("SourceTreeItem", () => {
 
       component.simulate("click", { event: "click" });
       expect(props.selectItem).not.toHaveBeenCalled();
     });
   });
 });
 
 function generateDefaults(overrides) {
-  const source = createSource({
-    id: "server1.conn13.child1/39",
-    url: "http://mdn.com/one.js"
-  });
+  const source = makeMockSource(
+    "http://mdn.com/one.js",
+    "server1.conn13.child1/39"
+  );
 
   const item = {
     name: "one.js",
     path: "mdn.com/one.js",
     contents: source
   };
 
   return {
     expanded: false,
     item,
     source,
     debuggeeUrl: "http://mdn.com",
     projectRoot: "",
     clearProjectDirectoryRoot: jest.fn(),
     setProjectDirectoryRoot: jest.fn(),
+    toggleBlackBox: jest.fn(),
     selectItem: jest.fn(),
     focusItem: jest.fn(),
     setExpanded: jest.fn(),
     ...overrides
   };
 }
 
 function render(overrides = {}) {
@@ -338,20 +385,20 @@ function createMockDirectory(path = "fol
     path,
     contents
   };
 }
 
 function createMockItem(overrides = {}) {
   overrides = {
     ...overrides,
-    contents: createSource({
-      id: "server1.conn13.child1/39",
+    contents: {
+      ...makeMockSource(undefined, "server1.conn13.child1/39"),
       ...(overrides.contents || {})
-    })
+    }
   };
 
   return {
     type: "source",
     name: "one.js",
     path: "http://mdn.com/one.js",
     ...overrides
   };
--- a/devtools/client/debugger/new/src/components/PrimaryPanes/tests/__snapshots__/SourcesTree.spec.js.snap
+++ b/devtools/client/debugger/new/src/components/PrimaryPanes/tests/__snapshots__/SourcesTree.spec.js.snap
@@ -117,124 +117,130 @@ exports[`SourcesTree on receiving new pr
       getChildren={[Function]}
       getParent={[Function]}
       getPath={[Function]}
       getRoots={[Function]}
       highlightItems={
         Array [
           Object {
             "contents": Object {
-              "contentType": "",
-              "error": undefined,
+              "actors": Array [],
+              "contentType": "text/javascript",
               "id": "server1.conn13.child1/41",
+              "introductionUrl": null,
               "isBlackBoxed": false,
               "isExtension": false,
               "isPrettyPrinted": false,
               "isWasm": false,
               "loadedState": "unloaded",
+              "relativeUrl": "http://mdn.com/three.js",
               "sourceMapURL": null,
-              "text": undefined,
-              "thread": "",
+              "text": "",
               "url": "http://mdn.com/three.js",
             },
             "name": "three.js",
             "path": "mdn.com/three.js",
             "type": "source",
           },
           Object {
             "contents": Array [
               Object {
                 "contents": Object {
-                  "contentType": "",
-                  "error": undefined,
+                  "actors": Array [],
+                  "contentType": "text/javascript",
                   "id": "server1.conn13.child1/42",
+                  "introductionUrl": null,
                   "isBlackBoxed": false,
                   "isExtension": false,
                   "isPrettyPrinted": false,
                   "isWasm": false,
                   "loadedState": "unloaded",
+                  "relativeUrl": "http://mdn.com/four.js",
                   "sourceMapURL": "data:application/json?charset=utf?dsffewrsf",
-                  "text": undefined,
-                  "thread": "",
+                  "text": "",
                   "url": "http://mdn.com/four.js",
                 },
                 "name": "four.js",
                 "path": "mdn.com/four.js",
                 "type": "source",
               },
               Object {
                 "contents": Object {
-                  "contentType": "",
-                  "error": undefined,
+                  "actors": Array [],
+                  "contentType": "text/javascript",
                   "id": "server1.conn13.child1/42/originalSource-sha",
+                  "introductionUrl": null,
                   "isBlackBoxed": false,
                   "isExtension": false,
                   "isPrettyPrinted": false,
                   "isWasm": false,
                   "loadedState": "unloaded",
+                  "relativeUrl": "http://mdn.com/four.js",
                   "sourceMapURL": null,
-                  "text": undefined,
-                  "thread": "",
+                  "text": "",
                   "url": "http://mdn.com/four.js",
                 },
                 "name": "four.js",
                 "path": "mdn.com/four.js",
                 "type": "source",
               },
               Object {
                 "contents": Object {
-                  "contentType": "",
-                  "error": undefined,
+                  "actors": Array [],
+                  "contentType": "text/javascript",
                   "id": "server1.conn13.child1/39",
+                  "introductionUrl": null,
                   "isBlackBoxed": false,
                   "isExtension": false,
                   "isPrettyPrinted": false,
                   "isWasm": false,
                   "loadedState": "unloaded",
+                  "relativeUrl": "http://mdn.com/one.js",
                   "sourceMapURL": null,
-                  "text": undefined,
-                  "thread": "",
+                  "text": "",
                   "url": "http://mdn.com/one.js",
                 },
                 "name": "one.js",
                 "path": "mdn.com/one.js",
                 "type": "source",
               },
               Object {
                 "contents": Object {
-                  "contentType": "",
-                  "error": undefined,
+                  "actors": Array [],
+                  "contentType": "text/javascript",
                   "id": "server1.conn13.child1/41",
+                  "introductionUrl": null,
                   "isBlackBoxed": false,
                   "isExtension": false,
                   "isPrettyPrinted": false,
                   "isWasm": false,
                   "loadedState": "unloaded",
+                  "relativeUrl": "http://mdn.com/three.js",
                   "sourceMapURL": null,
-                  "text": undefined,
-                  "thread": "",
+                  "text": "",
                   "url": "http://mdn.com/three.js",
                 },
                 "name": "three.js",
                 "path": "mdn.com/three.js",
                 "type": "source",
               },
               Object {
                 "contents": Object {
-                  "contentType": "",
-                  "error": undefined,
+                  "actors": Array [],
+                  "contentType": "text/javascript",
                   "id": "server1.conn13.child1/40",
+                  "introductionUrl": null,
                   "isBlackBoxed": false,
                   "isExtension": false,
                   "isPrettyPrinted": false,
                   "isWasm": false,
                   "loadedState": "unloaded",
+                  "relativeUrl": "http://mdn.com/two.js",
                   "sourceMapURL": null,
-                  "text": undefined,
-                  "thread": "",
+                  "text": "",
                   "url": "http://mdn.com/two.js",
                 },
                 "name": "two.js",
                 "path": "mdn.com/two.js",
                 "type": "source",
               },
             ],
             "name": "mdn.com",
--- a/devtools/client/debugger/new/src/components/PrimaryPanes/tests/__snapshots__/SourcesTreeItem.spec.js.snap
+++ b/devtools/client/debugger/new/src/components/PrimaryPanes/tests/__snapshots__/SourcesTreeItem.spec.js.snap
@@ -9,26 +9,27 @@ Object {
     onContextMenu={[Function]}
   >
     <span
       className="img no-arrow"
     />
     <Connect(SourceIcon)
       source={
         Object {
-          "contentType": "",
-          "error": undefined,
+          "actors": Array [],
+          "contentType": "text/javascript",
           "id": "server1.conn13.child1/39",
+          "introductionUrl": null,
           "isBlackBoxed": false,
           "isExtension": false,
           "isPrettyPrinted": false,
           "isWasm": false,
           "loadedState": "unloaded",
-          "sourceMapURL": undefined,
-          "text": undefined,
+          "relativeUrl": "http://mdn.com/one.js",
+          "text": "",
           "url": "http://mdn.com/one.js",
         }
       }
     />
     <span
       className="label"
     >
        
@@ -44,123 +45,130 @@ Object {
     "onContextMenu": [Function],
     "props": Object {
       "clearProjectDirectoryRoot": [MockFunction],
       "debuggeeUrl": "http://mdn.com",
       "expanded": false,
       "focusItem": [MockFunction],
       "item": Object {
         "contents": Object {
-          "contentType": "",
-          "error": undefined,
+          "actors": Array [],
+          "contentType": "text/javascript",
           "id": "server1.conn13.child1/39",
+          "introductionUrl": null,
           "isBlackBoxed": false,
           "isExtension": false,
           "isPrettyPrinted": false,
           "isWasm": false,
           "loadedState": "unloaded",
-          "sourceMapURL": undefined,
-          "text": undefined,
+          "relativeUrl": "http://mdn.com/one.js",
+          "text": "",
           "url": "http://mdn.com/one.js",
         },
         "name": "one.js",
         "path": "mdn.com/one.js",
       },
       "projectRoot": "root/",
       "selectItem": [MockFunction],
       "setExpanded": [MockFunction],
       "setProjectDirectoryRoot": [MockFunction],
       "source": Object {
-        "contentType": "",
-        "error": undefined,
+        "actors": Array [],
+        "contentType": "text/javascript",
         "id": "server1.conn13.child1/39",
+        "introductionUrl": null,
         "isBlackBoxed": false,
         "isExtension": false,
         "isPrettyPrinted": false,
         "isWasm": false,
         "loadedState": "unloaded",
-        "sourceMapURL": undefined,
-        "text": undefined,
+        "relativeUrl": "http://mdn.com/one.js",
+        "text": "",
         "url": "http://mdn.com/one.js",
       },
+      "toggleBlackBox": [MockFunction],
     },
     "refs": Object {},
     "state": null,
     "updater": Updater {
       "_callbacks": Array [],
       "_renderer": ReactShallowRenderer {
         "_context": Object {},
         "_element": <SourceTreeItem
           clearProjectDirectoryRoot={[MockFunction]}
           debuggeeUrl="http://mdn.com"
           expanded={false}
           focusItem={[MockFunction]}
           item={
             Object {
               "contents": Object {
-                "contentType": "",
-                "error": undefined,
+                "actors": Array [],
+                "contentType": "text/javascript",
                 "id": "server1.conn13.child1/39",
+                "introductionUrl": null,
                 "isBlackBoxed": false,
                 "isExtension": false,
                 "isPrettyPrinted": false,
                 "isWasm": false,
                 "loadedState": "unloaded",
-                "sourceMapURL": undefined,
-                "text": undefined,
+                "relativeUrl": "http://mdn.com/one.js",
+                "text": "",
                 "url": "http://mdn.com/one.js",
               },
               "name": "one.js",
               "path": "mdn.com/one.js",
             }
           }
           projectRoot="root/"
           selectItem={[MockFunction]}
           setExpanded={[MockFunction]}
           setProjectDirectoryRoot={[MockFunction]}
           source={
             Object {
-              "contentType": "",
-              "error": undefined,
+              "actors": Array [],
+              "contentType": "text/javascript",
               "id": "server1.conn13.child1/39",
+              "introductionUrl": null,
               "isBlackBoxed": false,
               "isExtension": false,
               "isPrettyPrinted": false,
               "isWasm": false,
               "loadedState": "unloaded",
-              "sourceMapURL": undefined,
-              "text": undefined,
+              "relativeUrl": "http://mdn.com/one.js",
+              "text": "",
               "url": "http://mdn.com/one.js",
             }
           }
+          toggleBlackBox={[MockFunction]}
         />,
         "_forcedUpdate": false,
         "_instance": [Circular],
         "_newState": null,
         "_rendered": <div
           className="node"
           onClick={[Function]}
           onContextMenu={[Function]}
         >
           <span
             className="img no-arrow"
           />
           <Connect(SourceIcon)
             source={
               Object {
-                "contentType": "",
-                "error": undefined,
+                "actors": Array [],
+                "contentType": "text/javascript",
                 "id": "server1.conn13.child1/39",
+                "introductionUrl": null,
                 "isBlackBoxed": false,
                 "isExtension": false,
                 "isPrettyPrinted": false,
                 "isWasm": false,
                 "loadedState": "unloaded",
-                "sourceMapURL": undefined,
-                "text": undefined,
+                "relativeUrl": "http://mdn.com/one.js",
+                "text": "",
                 "url": "http://mdn.com/one.js",
               }
             }
           />
           <span
             className="label"
           >
              
@@ -175,48 +183,51 @@ Object {
   },
   "props": Object {
     "clearProjectDirectoryRoot": [MockFunction],
     "debuggeeUrl": "http://mdn.com",
     "expanded": false,
     "focusItem": [MockFunction],
     "item": Object {
       "contents": Object {
-        "contentType": "",
-        "error": undefined,
+        "actors": Array [],
+        "contentType": "text/javascript",
         "id": "server1.conn13.child1/39",
+        "introductionUrl": null,
         "isBlackBoxed": false,
         "isExtension": false,
         "isPrettyPrinted": false,
         "isWasm": false,
         "loadedState": "unloaded",
-        "sourceMapURL": undefined,
-        "text": undefined,
+        "relativeUrl": "http://mdn.com/one.js",
+        "text": "",
         "url": "http://mdn.com/one.js",
       },
       "name": "one.js",
       "path": "mdn.com/one.js",
     },
     "projectRoot": "root/",
     "selectItem": [MockFunction],
     "setExpanded": [MockFunction],
     "setProjectDirectoryRoot": [MockFunction],
     "source": Object {
-      "contentType": "",
-      "error": undefined,
+      "actors": Array [],
+      "contentType": "text/javascript",
       "id": "server1.conn13.child1/39",
+      "introductionUrl": null,
       "isBlackBoxed": false,
       "isExtension": false,
       "isPrettyPrinted": false,
       "isWasm": false,
       "loadedState": "unloaded",
-      "sourceMapURL": undefined,
-      "text": undefined,
+      "relativeUrl": "http://mdn.com/one.js",
+      "text": "",
       "url": "http://mdn.com/one.js",
     },
+    "toggleBlackBox": [MockFunction],
   },
 }
 `;
 
 exports[`SourceTreeItem renderItem should show (mapped) for duplicate source items 1`] = `
 Object {
   "component": <div
     className="node"
@@ -225,26 +236,27 @@ Object {
     onContextMenu={[Function]}
   >
     <span
       className="img no-arrow"
     />
     <Connect(SourceIcon)
       source={
         Object {
-          "contentType": "",
-          "error": undefined,
+          "actors": Array [],
+          "contentType": "text/javascript",
           "id": "server1.conn13.child1/39",
+          "introductionUrl": null,
           "isBlackBoxed": false,
           "isExtension": false,
           "isPrettyPrinted": false,
           "isWasm": false,
           "loadedState": "unloaded",
-          "sourceMapURL": undefined,
-          "text": undefined,
+          "relativeUrl": "http://mdn.com/one.js",
+          "text": "",
           "url": "http://mdn.com/one.js",
         }
       }
     />
     <span
       className="label"
     >
        
@@ -266,126 +278,133 @@ Object {
     "props": Object {
       "clearProjectDirectoryRoot": [MockFunction],
       "debuggeeUrl": "http://mdn.com",
       "expanded": false,
       "focusItem": [MockFunction],
       "hasMatchingGeneratedSource": true,
       "item": Object {
         "contents": Object {
-          "contentType": "",
-          "error": undefined,
+          "actors": Array [],
+          "contentType": "text/javascript",
           "id": "server1.conn13.child1/39",
+          "introductionUrl": null,
           "isBlackBoxed": false,
           "isExtension": false,
           "isPrettyPrinted": false,
           "isWasm": false,
           "loadedState": "unloaded",
-          "sourceMapURL": undefined,
-          "text": undefined,
-          "url": undefined,
+          "relativeUrl": "url",
+          "text": "",
+          "url": "url",
         },
         "name": "one.js",
         "path": "http://mdn.com/one.js",
         "type": "source",
       },
       "projectRoot": "",
       "selectItem": [MockFunction],
       "setExpanded": [MockFunction],
       "setProjectDirectoryRoot": [MockFunction],
       "source": Object {
-        "contentType": "",
-        "error": undefined,
+        "actors": Array [],
+        "contentType": "text/javascript",
         "id": "server1.conn13.child1/39",
+        "introductionUrl": null,
         "isBlackBoxed": false,
         "isExtension": false,
         "isPrettyPrinted": false,
         "isWasm": false,
         "loadedState": "unloaded",
-        "sourceMapURL": undefined,
-        "text": undefined,
+        "relativeUrl": "http://mdn.com/one.js",
+        "text": "",
         "url": "http://mdn.com/one.js",
       },
+      "toggleBlackBox": [MockFunction],
     },
     "refs": Object {},
     "state": null,
     "updater": Updater {
       "_callbacks": Array [],
       "_renderer": ReactShallowRenderer {
         "_context": Object {},
         "_element": <SourceTreeItem
           clearProjectDirectoryRoot={[MockFunction]}
           debuggeeUrl="http://mdn.com"
           expanded={false}
           focusItem={[MockFunction]}
           hasMatchingGeneratedSource={true}
           item={
             Object {
               "contents": Object {
-                "contentType": "",
-                "error": undefined,
+                "actors": Array [],
+                "contentType": "text/javascript",
                 "id": "server1.conn13.child1/39",
+                "introductionUrl": null,
                 "isBlackBoxed": false,
                 "isExtension": false,
                 "isPrettyPrinted": false,
                 "isWasm": false,
                 "loadedState": "unloaded",
-                "sourceMapURL": undefined,
-                "text": undefined,
-                "url": undefined,
+                "relativeUrl": "url",
+                "text": "",
+                "url": "url",
               },
               "name": "one.js",
               "path": "http://mdn.com/one.js",
               "type": "source",
             }
           }
           projectRoot=""
           selectItem={[MockFunction]}
           setExpanded={[MockFunction]}
           setProjectDirectoryRoot={[MockFunction]}
           source={
             Object {
-              "contentType": "",
-              "error": undefined,
+              "actors": Array [],
+              "contentType": "text/javascript",
               "id": "server1.conn13.child1/39",
+              "introductionUrl": null,
               "isBlackBoxed": false,
               "isExtension": false,
               "isPrettyPrinted": false,
               "isWasm": false,
               "loadedState": "unloaded",
-              "sourceMapURL": undefined,
-              "text": undefined,
+              "relativeUrl": "http://mdn.com/one.js",
+              "text": "",
               "url": "http://mdn.com/one.js",
             }
           }
+          toggleBlackBox={[MockFunction]}
         />,
         "_forcedUpdate": false,
         "_instance": [Circular],
         "_newState": null,
         "_rendered": <div
           className="node"
           onClick={[Function]}
           onContextMenu={[Function]}
         >
           <span
             className="img no-arrow"
           />
           <Connect(SourceIcon)
             source={
               Object {
-                "contentType": "",
-                "error": undefined,
+                "actors": Array [],
+                "contentType": "text/javascript",
                 "id": "server1.conn13.child1/39",
+                "introductionUrl": null,
                 "isBlackBoxed": false,
                 "isExtension": false,
                 "isPrettyPrinted": false,
                 "isWasm": false,
                 "loadedState": "unloaded",
-                "sourceMapURL": undefined,
-                "text": undefined,
+                "relativeUrl": "http://mdn.com/one.js",
+                "text": "",
                 "url": "http://mdn.com/one.js",
               }
             }
           />
           <span
             className="label"
           >
              
@@ -406,49 +425,52 @@ Object {
   "props": Object {
     "clearProjectDirectoryRoot": [MockFunction],
     "debuggeeUrl": "http://mdn.com",
     "expanded": false,
     "focusItem": [MockFunction],
     "hasMatchingGeneratedSource": true,
     "item": Object {
       "contents": Object {
-        "contentType": "",
-        "error": undefined,
+        "actors": Array [],
+        "contentType": "text/javascript",
         "id": "server1.conn13.child1/39",
+        "introductionUrl": null,
         "isBlackBoxed": false,
         "isExtension": false,
         "isPrettyPrinted": false,
         "isWasm": false,
         "loadedState": "unloaded",
-        "sourceMapURL": undefined,
-        "text": undefined,
-        "url": undefined,
+        "relativeUrl": "url",
+        "text": "",
+        "url": "url",
       },
       "name": "one.js",
       "path": "http://mdn.com/one.js",
       "type": "source",
     },
     "projectRoot": "",
     "selectItem": [MockFunction],
     "setExpanded": [MockFunction],
     "setProjectDirectoryRoot": [MockFunction],
     "source": Object {
-      "contentType": "",
-      "error": undefined,
+      "actors": Array [],
+      "contentType": "text/javascript",
       "id": "server1.conn13.child1/39",
+      "introductionUrl": null,
       "isBlackBoxed": false,
       "isExtension": false,
       "isPrettyPrinted": false,
       "isWasm": false,
       "loadedState": "unloaded",
-      "sourceMapURL": undefined,
-      "text": undefined,
+      "relativeUrl": "http://mdn.com/one.js",
+      "text": "",
       "url": "http://mdn.com/one.js",
     },
+    "toggleBlackBox": [MockFunction],
   },
 }
 `;
 
 exports[`SourceTreeItem renderItem should show domain item 1`] = `
 Object {
   "component": <div
     className="node"
@@ -479,101 +501,107 @@ Object {
     "props": Object {
       "clearProjectDirectoryRoot": [MockFunction],
       "debuggeeUrl": "http://mdn.com",
       "depth": 0,
       "expanded": false,
       "focusItem": [MockFunction],
       "item": Object {
         "contents": Object {
-          "contentType": "",
-          "error": undefined,
+          "actors": Array [],
+          "contentType": "text/javascript",
           "id": "server1.conn13.child1/39",
+          "introductionUrl": null,
           "isBlackBoxed": false,
           "isExtension": false,
           "isPrettyPrinted": false,
           "isWasm": false,
           "loadedState": "unloaded",
-          "sourceMapURL": undefined,
-          "text": undefined,
-          "url": undefined,
+          "relativeUrl": "url",
+          "text": "",
+          "url": "url",
         },
         "name": "root",
         "path": "root",
         "type": "source",
       },
       "projectRoot": "",
       "selectItem": [MockFunction],
       "setExpanded": [MockFunction],
       "setProjectDirectoryRoot": [MockFunction],
       "source": Object {
-        "contentType": "",
-        "error": undefined,
+        "actors": Array [],
+        "contentType": "text/javascript",
         "id": "server1.conn13.child1/39",
+        "introductionUrl": null,
         "isBlackBoxed": false,
         "isExtension": false,
         "isPrettyPrinted": false,
         "isWasm": false,
         "loadedState": "unloaded",
-        "sourceMapURL": undefined,
-        "text": undefined,
+        "relativeUrl": "http://mdn.com/one.js",
+        "text": "",
         "url": "http://mdn.com/one.js",
       },
+      "toggleBlackBox": [MockFunction],
     },
     "refs": Object {},
     "state": null,
     "updater": Updater {
       "_callbacks": Array [],
       "_renderer": ReactShallowRenderer {
         "_context": Object {},
         "_element": <SourceTreeItem
           clearProjectDirectoryRoot={[MockFunction]}
           debuggeeUrl="http://mdn.com"
           depth={0}
           expanded={false}
           focusItem={[MockFunction]}
           item={
             Object {
               "contents": Object {
-                "contentType": "",
-                "error": undefined,
+                "actors": Array [],
+                "contentType": "text/javascript",
                 "id": "server1.conn13.child1/39",
+                "introductionUrl": null,
                 "isBlackBoxed": false,
                 "isExtension": false,
                 "isPrettyPrinted": false,
                 "isWasm": false,
                 "loadedState": "unloaded",
-                "sourceMapURL": undefined,
-                "text": undefined,
-                "url": undefined,
+                "relativeUrl": "url",
+                "text": "",
+                "url": "url",
               },
               "name": "root",
               "path": "root",
               "type": "source",
             }
           }
           projectRoot=""
           selectItem={[MockFunction]}
           setExpanded={[MockFunction]}
           setProjectDirectoryRoot={[MockFunction]}
           source={
             Object {
-              "contentType": "",
-              "error": undefined,
+              "actors": Array [],
+              "contentType": "text/javascript",
               "id": "server1.conn13.child1/39",
+              "introductionUrl": null,
               "isBlackBoxed": false,
               "isExtension": false,
               "isPrettyPrinted": false,
               "isWasm": false,
               "loadedState": "unloaded",
-              "sourceMapURL": undefined,
-              "text": undefined,
+              "relativeUrl": "http://mdn.com/one.js",
+              "text": "",
               "url": "http://mdn.com/one.js",
             }
           }
+          toggleBlackBox={[MockFunction]}
         />,
         "_forcedUpdate": false,
         "_instance": [Circular],
         "_newState": null,
         "_rendered": <div
           className="node"
           onClick={[Function]}
           onContextMenu={[Function]}
@@ -600,49 +628,52 @@ Object {
   "props": Object {
     "clearProjectDirectoryRoot": [MockFunction],
     "debuggeeUrl": "http://mdn.com",
     "depth": 0,
     "expanded": false,
     "focusItem": [MockFunction],
     "item": Object {
       "contents": Object {
-        "contentType": "",
-        "error": undefined,
+        "actors": Array [],
+        "contentType": "text/javascript",
         "id": "server1.conn13.child1/39",
+        "introductionUrl": null,
         "isBlackBoxed": false,
         "isExtension": false,
         "isPrettyPrinted": false,
         "isWasm": false,
         "loadedState": "unloaded",
-        "sourceMapURL": undefined,
-        "text": undefined,
-        "url": undefined,
+        "relativeUrl": "url",
+        "text": "",
+        "url": "url",
       },
       "name": "root",
       "path": "root",
       "type": "source",
     },
     "projectRoot": "",
     "selectItem": [MockFunction],
     "setExpanded": [MockFunction],
     "setProjectDirectoryRoot": [MockFunction],
     "source": Object {
-      "contentType": "",
-      "error": undefined,
+      "actors": Array [],
+      "contentType": "text/javascript",
       "id": "server1.conn13.child1/39",
+      "introductionUrl": null,
       "isBlackBoxed": false,
       "isExtension": false,
       "isPrettyPrinted": false,
       "isWasm": false,
       "loadedState": "unloaded",
-      "sourceMapURL": undefined,
-      "text": undefined,
+      "relativeUrl": "http://mdn.com/one.js",
+      "text": "",
       "url": "http://mdn.com/one.js",
     },
+    "toggleBlackBox": [MockFunction],
   },
 }
 `;
 
 exports[`SourceTreeItem renderItem should show domain item as debuggee 1`] = `
 Object {
   "component": <div
     className="node"
@@ -682,28 +713,30 @@ Object {
         "path": "root",
         "type": "directory",
       },
       "projectRoot": "",
       "selectItem": [MockFunction],
       "setExpanded": [MockFunction],
       "setProjectDirectoryRoot": [MockFunction],
       "source": Object {
-        "contentType": "",
-        "error": undefined,
+        "actors": Array [],
+        "contentType": "text/javascript",
         "id": "server1.conn13.child1/39",
+        "introductionUrl": null,
         "isBlackBoxed": false,
         "isExtension": false,
         "isPrettyPrinted": false,
         "isWasm": false,
         "loadedState": "unloaded",
-        "sourceMapURL": undefined,
-        "text": undefined,
+        "relativeUrl": "http://mdn.com/one.js",
+        "text": "",
         "url": "http://mdn.com/one.js",
       },
+      "toggleBlackBox": [MockFunction],
     },
     "refs": Object {},
     "state": null,
     "updater": Updater {
       "_callbacks": Array [],
       "_renderer": ReactShallowRenderer {
         "_context": Object {},
         "_element": <SourceTreeItem
@@ -721,29 +754,31 @@ Object {
             }
           }
           projectRoot=""
           selectItem={[MockFunction]}
           setExpanded={[MockFunction]}
           setProjectDirectoryRoot={[MockFunction]}
           source={
             Object {
-              "contentType": "",
-              "error": undefined,
+              "actors": Array [],
+              "contentType": "text/javascript",
               "id": "server1.conn13.child1/39",
+              "introductionUrl": null,
               "isBlackBoxed": false,
               "isExtension": false,
               "isPrettyPrinted": false,
               "isWasm": false,
               "loadedState": "unloaded",
-              "sourceMapURL": undefined,
-              "text": undefined,
+              "relativeUrl": "http://mdn.com/one.js",
+              "text": "",
               "url": "http://mdn.com/one.js",
             }
           }
+          toggleBlackBox={[MockFunction]}
         />,
         "_forcedUpdate": false,
         "_instance": [Circular],
         "_newState": null,
         "_rendered": <div
           className="node"
           onClick={[Function]}
           onContextMenu={[Function]}
@@ -779,28 +814,30 @@ Object {
       "path": "root",
       "type": "directory",
     },
     "projectRoot": "",
     "selectItem": [MockFunction],
     "setExpanded": [MockFunction],
     "setProjectDirectoryRoot": [MockFunction],
     "source": Object {
-      "contentType": "",
-      "error": undefined,
+      "actors": Array [],
+      "contentType": "text/javascript",
       "id": "server1.conn13.child1/39",
+      "introductionUrl": null,
       "isBlackBoxed": false,
       "isExtension": false,
       "isPrettyPrinted": false,
       "isWasm": false,
       "loadedState": "unloaded",
-      "sourceMapURL": undefined,
-      "text": undefined,
+      "relativeUrl": "http://mdn.com/one.js",
+      "text": "",
       "url": "http://mdn.com/one.js",
     },
+    "toggleBlackBox": [MockFunction],
   },
 }
 `;
 
 exports[`SourceTreeItem renderItem should show domain item as debuggee with focus and arrow 1`] = `
 Object {
   "component": <div
     className="node focused"
@@ -841,28 +878,30 @@ Object {
         "path": "root",
         "type": "directory",
       },
       "projectRoot": "",
       "selectItem": [MockFunction],
       "setExpanded": [MockFunction],
       "setProjectDirectoryRoot": [MockFunction],
       "source": Object {
-        "contentType": "",
-        "error": undefined,
+        "actors": Array [],
+        "contentType": "text/javascript",
         "id": "server1.conn13.child1/39",
+        "introductionUrl": null,
         "isBlackBoxed": false,
         "isExtension": false,
         "isPrettyPrinted": false,
         "isWasm": false,
         "loadedState": "unloaded",
-        "sourceMapURL": undefined,
-        "text": undefined,
+        "relativeUrl": "http://mdn.com/one.js",
+        "text": "",
         "url": "http://mdn.com/one.js",
       },
+      "toggleBlackBox": [MockFunction],
     },
     "refs": Object {},
     "state": null,
     "updater": Updater {
       "_callbacks": Array [],
       "_renderer": ReactShallowRenderer {
         "_context": Object {},
         "_element": <SourceTreeItem
@@ -881,29 +920,31 @@ Object {
             }
           }
           projectRoot=""
           selectItem={[MockFunction]}
           setExpanded={[MockFunction]}
           setProjectDirectoryRoot={[MockFunction]}
           source={
             Object {
-              "contentType": "",
-              "error": undefined,
+              "actors": Array [],
+              "contentType": "text/javascript",
               "id": "server1.conn13.child1/39",
+              "introductionUrl": null,
               "isBlackBoxed": false,
               "isExtension": false,
               "isPrettyPrinted": false,
               "isWasm": false,
               "loadedState": "unloaded",
-              "sourceMapURL": undefined,
-              "text": undefined,
+              "relativeUrl": "http://mdn.com/one.js",
+              "text": "",
               "url": "http://mdn.com/one.js",
             }
           }
+          toggleBlackBox={[MockFunction]}
         />,
         "_forcedUpdate": false,
         "_instance": [Circular],
         "_newState": null,
         "_rendered": <div
           className="node focused"
           onClick={[Function]}
           onContextMenu={[Function]}
@@ -940,28 +981,30 @@ Object {
       "path": "root",
       "type": "directory",
     },
     "projectRoot": "",
     "selectItem": [MockFunction],
     "setExpanded": [MockFunction],
     "setProjectDirectoryRoot": [MockFunction],
     "source": Object {
-      "contentType": "",
-      "error": undefined,
+      "actors": Array [],
+      "contentType": "text/javascript",
       "id": "server1.conn13.child1/39",
+      "introductionUrl": null,
       "isBlackBoxed": false,
       "isExtension": false,
       "isPrettyPrinted": false,
       "isWasm": false,
       "loadedState": "unloaded",
-      "sourceMapURL": undefined,
-      "text": undefined,
+      "relativeUrl": "http://mdn.com/one.js",
+      "text": "",
       "url": "http://mdn.com/one.js",
     },
+    "toggleBlackBox": [MockFunction],
   },
 }
 `;
 
 exports[`SourceTreeItem renderItem should show focused item for folder with expanded arrow 1`] = `
 Object {
   "component": <div
     className="node focused"
@@ -1002,16 +1045,17 @@ Object {
         "path": "folder/",
         "type": "directory",
       },
       "projectRoot": "",
       "selectItem": [MockFunction],
       "setExpanded": [MockFunction],
       "setProjectDirectoryRoot": [MockFunction],
       "source": null,
+      "toggleBlackBox": [MockFunction],
     },
     "refs": Object {},
     "state": null,
     "updater": Updater {
       "_callbacks": Array [],
       "_renderer": ReactShallowRenderer {
         "_context": Object {},
         "_element": <SourceTreeItem
@@ -1029,16 +1073,17 @@ Object {
               "type": "directory",
             }
           }
           projectRoot=""
           selectItem={[MockFunction]}
           setExpanded={[MockFunction]}
           setProjectDirectoryRoot={[MockFunction]}
           source={null}
+          toggleBlackBox={[MockFunction]}
         />,
         "_forcedUpdate": false,
         "_instance": [Circular],
         "_newState": null,
         "_rendered": <div
           className="node focused"
           onClick={[Function]}
           onContextMenu={[Function]}
@@ -1075,16 +1120,17 @@ Object {
       "path": "folder/",
       "type": "directory",
     },
     "projectRoot": "",
     "selectItem": [MockFunction],
     "setExpanded": [MockFunction],
     "setProjectDirectoryRoot": [MockFunction],
     "source": null,
+    "toggleBlackBox": [MockFunction],
   },
 }
 `;
 
 exports[`SourceTreeItem renderItem should show icon for angular item 1`] = `
 Object {
   "component": <div
     className="node"
@@ -1123,28 +1169,30 @@ Object {
         "path": "ng://",
         "type": "directory",
       },
       "projectRoot": "",
       "selectItem": [MockFunction],
       "setExpanded": [MockFunction],
       "setProjectDirectoryRoot": [MockFunction],
       "source": Object {
-        "contentType": "",
-        "error": undefined,
+        "actors": Array [],
+        "contentType": "text/javascript",
         "id": "server1.conn13.child1/39",
+        "introductionUrl": null,
         "isBlackBoxed": false,
         "isExtension": false,
         "isPrettyPrinted": false,
         "isWasm": false,
         "loadedState": "unloaded",
-        "sourceMapURL": undefined,
-        "text": undefined,
+        "relativeUrl": "http://mdn.com/one.js",
+        "text": "",
         "url": "http://mdn.com/one.js",
       },
+      "toggleBlackBox": [MockFunction],
     },
     "refs": Object {},
     "state": null,
     "updater": Updater {
       "_callbacks": Array [],
       "_renderer": ReactShallowRenderer {
         "_context": Object {},
         "_element": <SourceTreeItem
@@ -1161,29 +1209,31 @@ Object {
             }
           }
           projectRoot=""
           selectItem={[MockFunction]}
           setExpanded={[MockFunction]}
           setProjectDirectoryRoot={[MockFunction]}
           source={
             Object {
-              "contentType": "",
-              "error": undefined,
+              "actors": Array [],
+              "contentType": "text/javascript",
               "id": "server1.conn13.child1/39",
+              "introductionUrl": null,
               "isBlackBoxed": false,
               "isExtension": false,
               "isPrettyPrinted": false,
               "isWasm": false,
               "loadedState": "unloaded",
-              "sourceMapURL": undefined,
-              "text": undefined,
+              "relativeUrl": "http://mdn.com/one.js",
+              "text": "",
               "url": "http://mdn.com/one.js",
             }
           }
+          toggleBlackBox={[MockFunction]}
         />,
         "_forcedUpdate": false,
         "_instance": [Circular],
         "_newState": null,
         "_rendered": <div
           className="node"
           onClick={[Function]}
           onContextMenu={[Function]}
@@ -1218,28 +1268,30 @@ Object {
       "path": "ng://",
       "type": "directory",
     },
     "projectRoot": "",
     "selectItem": [MockFunction],
     "setExpanded": [MockFunction],
     "setProjectDirectoryRoot": [MockFunction],
     "source": Object {
-      "contentType": "",
-      "error": undefined,
+      "actors": Array [],
+      "contentType": "text/javascript",
       "id": "server1.conn13.child1/39",
+      "introductionUrl": null,
       "isBlackBoxed": false,
       "isExtension": false,
       "isPrettyPrinted": false,
       "isWasm": false,
       "loadedState": "unloaded",
-      "sourceMapURL": undefined,
-      "text": undefined,
+      "relativeUrl": "http://mdn.com/one.js",
+      "text": "",
       "url": "http://mdn.com/one.js",
     },
+    "toggleBlackBox": [MockFunction],
   },
 }
 `;
 
 exports[`SourceTreeItem renderItem should show icon for folder with arrow 1`] = `
 Object {
   "component": <div
     className="node"
@@ -1278,16 +1330,17 @@ Object {
         "path": "folder/",
         "type": "directory",
       },
       "projectRoot": "",
       "selectItem": [MockFunction],
       "setExpanded": [MockFunction],
       "setProjectDirectoryRoot": [MockFunction],
       "source": null,
+      "toggleBlackBox": [MockFunction],
     },
     "refs": Object {},
     "state": null,
     "updater": Updater {
       "_callbacks": Array [],
       "_renderer": ReactShallowRenderer {
         "_context": Object {},
         "_element": <SourceTreeItem
@@ -1303,16 +1356,17 @@ Object {
               "type": "directory",
             }
           }
           projectRoot=""
           selectItem={[MockFunction]}
           setExpanded={[MockFunction]}
           setProjectDirectoryRoot={[MockFunction]}
           source={null}
+          toggleBlackBox={[MockFunction]}
         />,
         "_forcedUpdate": false,
         "_instance": [Circular],
         "_newState": null,
         "_rendered": <div
           className="node"
           onClick={[Function]}
           onContextMenu={[Function]}
@@ -1347,16 +1401,17 @@ Object {
       "path": "folder/",
       "type": "directory",
     },
     "projectRoot": "",
     "selectItem": [MockFunction],
     "setExpanded": [MockFunction],
     "setProjectDirectoryRoot": [MockFunction],
     "source": null,
+    "toggleBlackBox": [MockFunction],
   },
 }
 `;
 
 exports[`SourceTreeItem renderItem should show icon for folder with expanded arrow 1`] = `
 Object {
   "component": <div
     className="node"
@@ -1397,16 +1452,17 @@ Object {
         "path": "folder/",
         "type": "directory",
       },
       "projectRoot": "",
       "selectItem": [MockFunction],
       "setExpanded": [MockFunction],
       "setProjectDirectoryRoot": [MockFunction],
       "source": null,
+      "toggleBlackBox": [MockFunction],
     },
     "refs": Object {},
     "state": null,
     "updater": Updater {
       "_callbacks": Array [],
       "_renderer": ReactShallowRenderer {
         "_context": Object {},
         "_element": <SourceTreeItem
@@ -1424,16 +1480,17 @@ Object {
               "type": "directory",
             }
           }
           projectRoot=""
           selectItem={[MockFunction]}
           setExpanded={[MockFunction]}
           setProjectDirectoryRoot={[MockFunction]}
           source={null}
+          toggleBlackBox={[MockFunction]}
         />,
         "_forcedUpdate": false,
         "_instance": [Circular],
         "_newState": null,
         "_rendered": <div
           className="node"
           onClick={[Function]}
           onContextMenu={[Function]}
@@ -1470,16 +1527,17 @@ Object {
       "path": "folder/",
       "type": "directory",
     },
     "projectRoot": "",
     "selectItem": [MockFunction],
     "setExpanded": [MockFunction],
     "setProjectDirectoryRoot": [MockFunction],
     "source": null,
+    "toggleBlackBox": [MockFunction],
   },
 }
 `;
 
 exports[`SourceTreeItem renderItem should show icon for moz-extension item 1`] = `
 Object {
   "component": <div
     className="node"
@@ -1519,28 +1577,30 @@ Object {
         "path": "moz-extension://e37c3c08-beac-a04b-8032-c4f699a1a856",
         "type": "directory",
       },
       "projectRoot": "",
       "selectItem": [MockFunction],
       "setExpanded": [MockFunction],
       "setProjectDirectoryRoot": [MockFunction],
       "source": Object {
-        "contentType": "",
-        "error": undefined,
+        "actors": Array [],
+        "contentType": "text/javascript",
         "id": "server1.conn13.child1/39",
+        "introductionUrl": null,
         "isBlackBoxed": false,
         "isExtension": false,
         "isPrettyPrinted": false,
         "isWasm": false,
         "loadedState": "unloaded",
-        "sourceMapURL": undefined,
-        "text": undefined,
+        "relativeUrl": "http://mdn.com/one.js",
+        "text": "",
         "url": "http://mdn.com/one.js",
       },
+      "toggleBlackBox": [MockFunction],
     },
     "refs": Object {},
     "state": null,
     "updater": Updater {
       "_callbacks": Array [],
       "_renderer": ReactShallowRenderer {
         "_context": Object {},
         "_element": <SourceTreeItem
@@ -1558,29 +1618,31 @@ Object {
             }
           }
           projectRoot=""
           selectItem={[MockFunction]}
           setExpanded={[MockFunction]}
           setProjectDirectoryRoot={[MockFunction]}
           source={
             Object {
-              "contentType": "",
-              "error": undefined,
+              "actors": Array [],
+              "contentType": "text/javascript",
               "id": "server1.conn13.child1/39",
+              "introductionUrl": null,
               "isBlackBoxed": false,
               "isExtension": false,
               "isPrettyPrinted": false,
               "isWasm": false,
               "loadedState": "unloaded",
-              "sourceMapURL": undefined,
-              "text": undefined,
+              "relativeUrl": "http://mdn.com/one.js",
+              "text": "",
               "url": "http://mdn.com/one.js",
             }
           }
+          toggleBlackBox={[MockFunction]}
         />,
         "_forcedUpdate": false,
         "_instance": [Circular],
         "_newState": null,
         "_rendered": <div
           className="node"
           onClick={[Function]}
           onContextMenu={[Function]}
@@ -1616,28 +1678,30 @@ Object {
       "path": "moz-extension://e37c3c08-beac-a04b-8032-c4f699a1a856",
       "type": "directory",
     },
     "projectRoot": "",
     "selectItem": [MockFunction],
     "setExpanded": [MockFunction],
     "setProjectDirectoryRoot": [MockFunction],
     "source": Object {
-      "contentType": "",
-      "error": undefined,
+      "actors": Array [],
+      "contentType": "text/javascript",
       "id": "server1.conn13.child1/39",
+      "introductionUrl": null,
       "isBlackBoxed": false,
       "isExtension": false,
       "isPrettyPrinted": false,
       "isWasm": false,
       "loadedState": "unloaded",
-      "sourceMapURL": undefined,
-      "text": undefined,
+      "relativeUrl": "http://mdn.com/one.js",
+      "text": "",
       "url": "http://mdn.com/one.js",
     },
+    "toggleBlackBox": [MockFunction],
   },
 }
 `;
 
 exports[`SourceTreeItem renderItem should show icon for webpack item 1`] = `
 Object {
   "component": <div
     className="node"
@@ -1676,28 +1740,30 @@ Object {
         "path": "webpack://",
         "type": "directory",
       },
       "projectRoot": "",
       "selectItem": [MockFunction],
       "setExpanded": [MockFunction],
       "setProjectDirectoryRoot": [MockFunction],
       "source": Object {
-        "contentType": "",
-        "error": undefined,
+        "actors": Array [],
+        "contentType": "text/javascript",
         "id": "server1.conn13.child1/39",
+        "introductionUrl": null,
         "isBlackBoxed": false,
         "isExtension": false,
         "isPrettyPrinted": false,
         "isWasm": false,
         "loadedState": "unloaded",
-        "sourceMapURL": undefined,
-        "text": undefined,
+        "relativeUrl": "http://mdn.com/one.js",
+        "text": "",
         "url": "http://mdn.com/one.js",
       },
+      "toggleBlackBox": [MockFunction],
     },
     "refs": Object {},
     "state": null,
     "updater": Updater {
       "_callbacks": Array [],
       "_renderer": ReactShallowRenderer {
         "_context": Object {},
         "_element": <SourceTreeItem
@@ -1714,29 +1780,31 @@ Object {
             }
           }
           projectRoot=""
           selectItem={[MockFunction]}
           setExpanded={[MockFunction]}
           setProjectDirectoryRoot={[MockFunction]}
           source={
             Object {
-              "contentType": "",
-              "error": undefined,
+              "actors": Array [],
+              "contentType": "text/javascript",
               "id": "server1.conn13.child1/39",
+              "introductionUrl": null,
               "isBlackBoxed": false,
               "isExtension": false,
               "isPrettyPrinted": false,
               "isWasm": false,
               "loadedState": "unloaded",
-              "sourceMapURL": undefined,
-              "text": undefined,
+              "relativeUrl": "http://mdn.com/one.js",
+              "text": "",
               "url": "http://mdn.com/one.js",
             }
           }
+          toggleBlackBox={[MockFunction]}
         />,
         "_forcedUpdate": false,
         "_instance": [Circular],
         "_newState": null,
         "_rendered": <div
           className="node"
           onClick={[Function]}
           onContextMenu={[Function]}
@@ -1771,28 +1839,30 @@ Object {
       "path": "webpack://",
       "type": "directory",
     },
     "projectRoot": "",
     "selectItem": [MockFunction],
     "setExpanded": [MockFunction],
     "setProjectDirectoryRoot": [MockFunction],
     "source": Object {
-      "contentType": "",
-      "error": undefined,
+      "actors": Array [],
+      "contentType": "text/javascript",
       "id": "server1.conn13.child1/39",
+      "introductionUrl": null,
       "isBlackBoxed": false,
       "isExtension": false,
       "isPrettyPrinted": false,
       "isWasm": false,
       "loadedState": "unloaded",
-      "sourceMapURL": undefined,
-      "text": undefined,
+      "relativeUrl": "http://mdn.com/one.js",
+      "text": "",
       "url": "http://mdn.com/one.js",
     },
+    "toggleBlackBox": [MockFunction],
   },
 }
 `;
 
 exports[`SourceTreeItem renderItem should show source item with source icon 1`] = `
 Object {
   "component": <div
     className="node"
@@ -1801,26 +1871,27 @@ Object {
     onContextMenu={[Function]}
   >
     <span
       className="img no-arrow"
     />
     <Connect(SourceIcon)
       source={
         Object {
-          "contentType": "",
-          "error": undefined,
+          "actors": Array [],
+          "contentType": "text/javascript",
           "id": "server1.conn13.child1/39",
+          "introductionUrl": null,
           "isBlackBoxed": false,
           "isExtension": false,
           "isPrettyPrinted": false,
           "isWasm": false,
           "loadedState": "unloaded",
-          "sourceMapURL": undefined,
-          "text": undefined,
+          "relativeUrl": "http://mdn.com/one.js",
+          "text": "",
           "url": "http://mdn.com/one.js",
         }
       }
     />
     <span
       className="label"
     >
        
@@ -1836,125 +1907,132 @@ Object {
     "onContextMenu": [Function],
     "props": Object {
       "clearProjectDirectoryRoot": [MockFunction],
       "debuggeeUrl": "http://mdn.com",
       "expanded": false,
       "focusItem": [MockFunction],
       "item": Object {
         "contents": Object {
-          "contentType": "",
-          "error": undefined,
+          "actors": Array [],
+          "contentType": "text/javascript",
           "id": "server1.conn13.child1/39",
+          "introductionUrl": null,
           "isBlackBoxed": false,
           "isExtension": false,
           "isPrettyPrinted": false,
           "isWasm": false,
           "loadedState": "unloaded",
-          "sourceMapURL": undefined,
-          "text": undefined,
-          "url": undefined,
+          "relativeUrl": "url",
+          "text": "",
+          "url": "url",
         },
         "name": "one.js",
         "path": "http://mdn.com/one.js",
         "type": "source",
       },
       "projectRoot": "",
       "selectItem": [MockFunction],
       "setExpanded": [MockFunction],
       "setProjectDirectoryRoot": [MockFunction],
       "source": Object {
-        "contentType": "",
-        "error": undefined,
+        "actors": Array [],
+        "contentType": "text/javascript",
         "id": "server1.conn13.child1/39",
+        "introductionUrl": null,
         "isBlackBoxed": false,
         "isExtension": false,
         "isPrettyPrinted": false,
         "isWasm": false,
         "loadedState": "unloaded",
-        "sourceMapURL": undefined,
-        "text": undefined,
+        "relativeUrl": "http://mdn.com/one.js",
+        "text": "",
         "url": "http://mdn.com/one.js",
       },
+      "toggleBlackBox": [MockFunction],
     },
     "refs": Object {},
     "state": null,
     "updater": Updater {
       "_callbacks": Array [],
       "_renderer": ReactShallowRenderer {
         "_context": Object {},
         "_element": <SourceTreeItem
           clearProjectDirectoryRoot={[MockFunction]}
           debuggeeUrl="http://mdn.com"
           expanded={false}
           focusItem={[MockFunction]}
           item={
             Object {
               "contents": Object {
-                "contentType": "",
-                "error": undefined,
+                "actors": Array [],
+                "contentType": "text/javascript",
                 "id": "server1.conn13.child1/39",
+                "introductionUrl": null,
                 "isBlackBoxed": false,
                 "isExtension": false,
                 "isPrettyPrinted": false,
                 "isWasm": false,
                 "loadedState": "unloaded",
-                "sourceMapURL": undefined,
-                "text": undefined,
-                "url": undefined,
+                "relativeUrl": "url",
+                "text": "",
+                "url": "url",
               },
               "name": "one.js",
               "path": "http://mdn.com/one.js",
               "type": "source",
             }
           }
           projectRoot=""
           selectItem={[MockFunction]}
           setExpanded={[MockFunction]}
           setProjectDirectoryRoot={[MockFunction]}
           source={
             Object {
-              "contentType": "",
-              "error": undefined,
+              "actors": Array [],
+              "contentType": "text/javascript",
               "id": "server1.conn13.child1/39",
+              "introductionUrl": null,
               "isBlackBoxed": false,
               "isExtension": false,
               "isPrettyPrinted": false,
               "isWasm": false,
               "loadedState": "unloaded",
-              "sourceMapURL": undefined,
-              "text": undefined,
+              "relativeUrl": "http://mdn.com/one.js",
+              "text": "",
               "url": "http://mdn.com/one.js",
             }
           }
+          toggleBlackBox={[MockFunction]}
         />,
         "_forcedUpdate": false,
         "_instance": [Circular],
         "_newState": null,
         "_rendered": <div
           className="node"
           onClick={[Function]}
           onContextMenu={[Function]}
         >
           <span
             className="img no-arrow"
           />
           <Connect(SourceIcon)
             source={
               Object {
-                "contentType": "",
-                "error": undefined,
+                "actors": Array [],
+                "contentType": "text/javascript",
                 "id": "server1.conn13.child1/39",
+                "introductionUrl": null,
                 "isBlackBoxed": false,
                 "isExtension": false,
                 "isPrettyPrinted": false,
                 "isWasm": false,
                 "loadedState": "unloaded",
-                "sourceMapURL": undefined,
-                "text": undefined,
+                "relativeUrl": "http://mdn.com/one.js",
+                "text": "",
                 "url": "http://mdn.com/one.js",
               }
             }
           />
           <span
             className="label"
           >
              
@@ -1969,49 +2047,52 @@ Object {
   },
   "props": Object {
     "clearProjectDirectoryRoot": [MockFunction],
     "debuggeeUrl": "http://mdn.com",
     "expanded": false,
     "focusItem": [MockFunction],
     "item": Object {
       "contents": Object {
-        "contentType": "",
-        "error": undefined,
+        "actors": Array [],
+        "contentType": "text/javascript",
         "id": "server1.conn13.child1/39",
+        "introductionUrl": null,
         "isBlackBoxed": false,
         "isExtension": false,
         "isPrettyPrinted": false,
         "isWasm": false,
         "loadedState": "unloaded",
-        "sourceMapURL": undefined,
-        "text": undefined,
-        "url": undefined,
+        "relativeUrl": "url",
+        "text": "",
+        "url": "url",
       },
       "name": "one.js",
       "path": "http://mdn.com/one.js",
       "type": "source",
     },
     "projectRoot": "",
     "selectItem": [MockFunction],
     "setExpanded": [MockFunction],
     "setProjectDirectoryRoot": [MockFunction],
     "source": Object {
-      "contentType": "",
-      "error": undefined,
+      "actors": Array [],
+      "contentType": "text/javascript",
       "id": "server1.conn13.child1/39",
+      "introductionUrl": null,
       "isBlackBoxed": false,
       "isExtension": false,
       "isPrettyPrinted": false,
       "isWasm": false,
       "loadedState": "unloaded",
-      "sourceMapURL": undefined,
-      "text": undefined,
+      "relativeUrl": "http://mdn.com/one.js",
+      "text": "",
       "url": "http://mdn.com/one.js",
     },
+    "toggleBlackBox": [MockFunction],
   },
 }
 `;
 
 exports[`SourceTreeItem renderItem should show source item with source icon with focus 1`] = `
 Object {
   "component": <div
     className="node focused"
@@ -2020,26 +2101,27 @@ Object {
     onContextMenu={[Function]}
   >
     <span
       className="img no-arrow"
     />
     <Connect(SourceIcon)
       source={
         Object {
-          "contentType": "",
-          "error": undefined,
+          "actors": Array [],
+          "contentType": "text/javascript",
           "id": "server1.conn13.child1/39",
+          "introductionUrl": null,
           "isBlackBoxed": false,
           "isExtension": false,
           "isPrettyPrinted": false,
           "isWasm": false,
           "loadedState": "unloaded",
-          "sourceMapURL": undefined,
-          "text": undefined,
+          "relativeUrl": "http://mdn.com/one.js",
+          "text": "",
           "url": "http://mdn.com/one.js",
         }
       }
     />
     <span
       className="label"
     >
        
@@ -2057,48 +2139,51 @@ Object {
       "clearProjectDirectoryRoot": [MockFunction],
       "debuggeeUrl": "http://mdn.com",
       "depth": 1,
       "expanded": false,
       "focusItem": [MockFunction],
       "focused": true,
       "item": Object {
         "contents": Object {
-          "contentType": "",
-          "error": undefined,
+          "actors": Array [],
+          "contentType": "text/javascript",
           "id": "server1.conn13.child1/39",
+          "introductionUrl": null,
           "isBlackBoxed": false,
           "isExtension": false,
           "isPrettyPrinted": false,
           "isWasm": false,
           "loadedState": "unloaded",
-          "sourceMapURL": undefined,
-          "text": undefined,
+          "relativeUrl": "http://mdn.com/one.js",
+          "text": "",
           "url": "http://mdn.com/one.js",
         },
         "name": "one.js",
         "path": "mdn.com/one.js",
       },
       "projectRoot": "",
       "selectItem": [MockFunction],
       "setExpanded": [MockFunction],
       "setProjectDirectoryRoot": [MockFunction],
       "source": Object {
-        "contentType": "",
-        "error": undefined,
+        "actors": Array [],
+        "contentType": "text/javascript",
         "id": "server1.conn13.child1/39",
+        "introductionUrl": null,
         "isBlackBoxed": false,
         "isExtension": false,
         "isPrettyPrinted": false,
         "isWasm": false,
         "loadedState": "unloaded",
-        "sourceMapURL": undefined,
-        "text": undefined,
+        "relativeUrl": "http://mdn.com/one.js",
+        "text": "",
         "url": "http://mdn.com/one.js",
       },
+      "toggleBlackBox": [MockFunction],
     },
     "refs": Object {},
     "state": null,
     "updater": Updater {
       "_callbacks": Array [],
       "_renderer": ReactShallowRenderer {
         "_context": Object {},
         "_element": <SourceTreeItem
@@ -2106,76 +2191,80 @@ Object {
           debuggeeUrl="http://mdn.com"
           depth={1}
           expanded={false}
           focusItem={[MockFunction]}
           focused={true}
           item={
             Object {
               "contents": Object {
-                "contentType": "",
-                "error": undefined,
+                "actors": Array [],
+                "contentType": "text/javascript",
                 "id": "server1.conn13.child1/39",
+                "introductionUrl": null,
                 "isBlackBoxed": false,
                 "isExtension": false,
                 "isPrettyPrinted": false,
                 "isWasm": false,
                 "loadedState": "unloaded",
-                "sourceMapURL": undefined,
-                "text": undefined,
+                "relativeUrl": "http://mdn.com/one.js",
+                "text": "",
                 "url": "http://mdn.com/one.js",
               },
               "name": "one.js",
               "path": "mdn.com/one.js",
             }
           }
           projectRoot=""
           selectItem={[MockFunction]}
           setExpanded={[MockFunction]}
           setProjectDirectoryRoot={[MockFunction]}
           source={
             Object {
-              "contentType": "",
-              "error": undefined,
+              "actors": Array [],
+              "contentType": "text/javascript",
               "id": "server1.conn13.child1/39",
+              "introductionUrl": null,
               "isBlackBoxed": false,
               "isExtension": false,
               "isPrettyPrinted": false,
               "isWasm": false,
               "loadedState": "unloaded",
-              "sourceMapURL": undefined,
-              "text": undefined,
+              "relativeUrl": "http://mdn.com/one.js",
+              "text": "",
               "url": "http://mdn.com/one.js",
             }
           }
+          toggleBlackBox={[MockFunction]}
         />,
         "_forcedUpdate": false,
         "_instance": [Circular],
         "_newState": null,
         "_rendered": <div
           className="node focused"
           onClick={[Function]}
           onContextMenu={[Function]}
         >
           <span
             className="img no-arrow"
           />
           <Connect(SourceIcon)
             source={
               Object {
-                "contentType": "",
-                "error": undefined,
+                "actors": Array [],
+                "contentType": "text/javascript",
                 "id": "server1.conn13.child1/39",
+                "introductionUrl": null,
                 "isBlackBoxed": false,
                 "isExtension": false,
                 "isPrettyPrinted": false,
                 "isWasm": false,
                 "loadedState": "unloaded",
-                "sourceMapURL": undefined,
-                "text": undefined,
+                "relativeUrl": "http://mdn.com/one.js",
+                "text": "",
                 "url": "http://mdn.com/one.js",
               }
             }
           />
           <span
             className="label"
           >
              
@@ -2192,43 +2281,46 @@ Object {
     "clearProjectDirectoryRoot": [MockFunction],
     "debuggeeUrl": "http://mdn.com",
     "depth": 1,
     "expanded": false,
     "focusItem": [MockFunction],
     "focused": true,
     "item": Object {
       "contents": Object {
-        "contentType": "",
-        "error": undefined,
+        "actors": Array [],
+        "contentType": "text/javascript",
         "id": "server1.conn13.child1/39",
+        "introductionUrl": null,
         "isBlackBoxed": false,
         "isExtension": false,
         "isPrettyPrinted": false,
         "isWasm": false,
         "loadedState": "unloaded",
-        "sourceMapURL": undefined,
-        "text": undefined,
+        "relativeUrl": "http://mdn.com/one.js",
+        "text": "",
         "url": "http://mdn.com/one.js",
       },
       "name": "one.js",
       "path": "mdn.com/one.js",
     },
     "projectRoot": "",
     "selectItem": [MockFunction],
     "setExpanded": [MockFunction],
     "setProjectDirectoryRoot": [MockFunction],
     "source": Object {
-      "contentType": "",
-      "error": undefined,
+      "actors": Array [],
+      "contentType": "text/javascript",
       "id": "server1.conn13.child1/39",
+      "introductionUrl": null,
       "isBlackBoxed": false,
       "isExtension": false,
       "isPrettyPrinted": false,
       "isWasm": false,
       "loadedState": "unloaded",
-      "sourceMapURL": undefined,
-      "text": undefined,
+      "relativeUrl": "http://mdn.com/one.js",
+      "text": "",
       "url": "http://mdn.com/one.js",
     },
+    "toggleBlackBox": [MockFunction],
   },
 }
 `;
--- a/devtools/client/debugger/new/src/components/QuickOpenModal.js
+++ b/devtools/client/debugger/new/src/components/QuickOpenModal.js
@@ -5,17 +5,17 @@
 // @flow
 import React, { Component } from "react";
 import { connect } from "../utils/connect";
 import fuzzyAldrin from "fuzzaldrin-plus";
 import { basename } from "../utils/path";
 
 import actions from "../actions";
 import {
-  getRelativeSourcesList,
+  getDisplayedSourcesList,
   getQuickOpenEnabled,
   getQuickOpenQuery,
   getQuickOpenType,
   getSelectedSource,
   getSymbols,
   getTabs,
   isSymbolsLoading
 } from "../selectors";
@@ -415,17 +415,17 @@ export class QuickOpenModal extends Comp
 }
 
 /* istanbul ignore next: ignoring testing of redux connection stuff */
 function mapStateToProps(state) {
   const selectedSource = getSelectedSource(state);
 
   return {
     enabled: getQuickOpenEnabled(state),
-    sources: formatSources(getRelativeSourcesList(state), getTabs(state)),
+    sources: formatSources(getDisplayedSourcesList(state), getTabs(state)),
     selectedSource,
     symbols: formatSymbols(getSymbols(state, selectedSource)),
     symbolsLoading: isSymbolsLoading(state, selectedSource),
     query: getQuickOpenQuery(state),
     searchType: getQuickOpenType(state),
     tabs: getTabs(state)
   };
 }
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/tests/Breakpoint.spec.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/tests/Breakpoint.spec.js
@@ -26,17 +26,17 @@ describe("Breakpoint", () => {
       frame: { selectedLocation: generatedLocation }
     });
     expect(component).toMatchSnapshot();
   });
 
   it("paused at an original location", () => {
     const { component } = render(
       {
-        selectedSource: makeOriginalSource("foo").source,
+        selectedSource: makeOriginalSource("foo"),
         frame: { selectedLocation: location }
       },
       { location, options: {} }
     );
 
     expect(component).toMatchSnapshot();
   });
 
@@ -67,19 +67,19 @@ function makeBreakpoint(overrides = {}) 
     generatedLocation,
     disabled: false,
     options: {},
     ...overrides
   };
 }
 
 function generateDefaults(overrides = {}, breakpointOverrides = {}) {
-  const source = makeSource("foo").source;
+  const source = makeSource("foo");
   const breakpoint = makeBreakpoint(breakpointOverrides);
-  const selectedSource = makeSource("foo").source;
+  const selectedSource = makeSource("foo");
   return {
     source,
     breakpoint,
     selectedSource,
     frame: (null: any),
     ...overrides
   };
 }
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/CommandBar.css
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/CommandBar.css
@@ -37,17 +37,17 @@ html[dir="rtl"] .command-bar {
   color: var(--theme-highlight-blue);
 }
 
 .command-bar .subSettings {
   float: right;
 }
 
 .command-bar .active .disable-pausing {
-  background-color: var(--theme-highlight-blue);
+  background-color: var(--theme-icon-checked-color);
 }
 
 .bottom {
   border-bottom: none;
   background-color: var(--theme-body-background);
   border-top: 1px solid var(--theme-splitter-color);
   flex: none;
   height: var(--editor-footer-height);
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/EventListeners.css
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/EventListeners.css
@@ -1,25 +1,61 @@
 /* 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/>. */
 
 .event-listeners-content {
-	padding: 4px 20px;
+	padding-top: 4px;
+	padding-bottom: 4px;
+	padding-inline-start: 14px;
+	padding-inline-end: 20px;
 }
 
 .event-listeners-content ul {
 	padding: 0;
 	list-style-type: none;
 }
 
 .event-listener-group {
 	user-select: none;
 }
 
+.event-listener-header {
+	display: flex;
+	align-items: center;
+}
+
+.event-listener-expand {
+	border: none;
+	background: none;
+	padding: 4px 5px;
+	line-height: 12px;
+}
+
+.event-listener-expand:hover {
+	background: transparent;
+}
+
+.event-listener-group input[type="checkbox"] {
+	margin: 0px;
+	margin-inline-end: 4px;
+}
+
+.event-listener-label {
+	display: flex;
+	align-items: center;
+	padding-inline-start: 2px;
+	padding-inline-end: 10px;
+}
+
+.event-listener-category {
+	padding: 3px 0px;
+	line-height: 14px;
+}
+
 .event-listeners-content .arrow {
 	margin-inline-end: 0;
 }
 
 html[dir="ltr"] .event-listeners-content .arrow.expanded {
   transform: rotate(0deg);
 }
 
@@ -28,12 +64,19 @@ html[dir="rtl"] .event-listeners-content
 }
 
 .event-listener-event {
 	display: flex;
 	align-items: center;
 	margin-inline-start: 30px;
 }
 
+.event-listener-name {
+	line-height: 14px;
+	padding: 3px 0px;
+}
+
 .event-listener-event input {
 	margin-inline-end: 4px;
 	margin-inline-start: 0px;
+	margin-top: 0px;
+	margin-bottom: 0px;
 }
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/EventListeners.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/EventListeners.js
@@ -41,18 +41,16 @@ class EventListeners extends Component<P
     super(props);
 
     this.state = {
       expandedCategories: []
     };
   }
 
   onCategoryToggle(category, event) {
-    event.preventDefault();
-
     const { expandedCategories } = this.state;
 
     if (expandedCategories.includes(category)) {
       this.setState({
         expandedCategories: expandedCategories.filter(
           eventCategory => eventCategory !== category
         )
       });