Revert "Backed out 19 changesets (bug 1525492) for damp timeout on a CLOSED TREE"
authorJason Laster <jlaster@mozilla.com>
Wed, 06 Feb 2019 18:16:47 -0800
changeset 457525 cd7226068bbc06f1a915f1fa749688e6f94492a2
parent 457524 76e0d806619a5954ac5341f7330fbde3be3d5f4c
child 457526 85c562f9b5fd1d8aa5c4b9d6e532b96cb6a0c798
push id111734
push userjlaster@mozilla.com
push dateThu, 07 Feb 2019 06:14:53 +0000
treeherdermozilla-inbound@85c562f9b5fd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1525492
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Revert "Backed out 19 changesets (bug 1525492) for damp timeout on a CLOSED TREE" This reverts commit 8e6a625a9ddaf8293811737accaf55158a05158a.
devtools/client/debugger/new/README.mozilla
devtools/client/debugger/new/dist/debugger.css
devtools/client/debugger/new/dist/parser-worker.js
devtools/client/debugger/new/dist/search-worker.js
devtools/client/debugger/new/dist/vendors.css
devtools/client/debugger/new/dist/vendors.js
devtools/client/debugger/new/images/moz.build
devtools/client/debugger/new/images/pane-collapse.svg
devtools/client/debugger/new/images/pane-expand.svg
devtools/client/debugger/new/images/toggle-panes.svg
devtools/client/debugger/new/src/actions/ast/setInScopeLines.js
devtools/client/debugger/new/src/actions/navigation.js
devtools/client/debugger/new/src/actions/pause/mapFrames.js
devtools/client/debugger/new/src/actions/pause/tests/pause.spec.js
devtools/client/debugger/new/src/actions/tests/__snapshots__/pending-breakpoints.spec.js.snap
devtools/client/debugger/new/src/actions/tests/helpers/breakpoints.js
devtools/client/debugger/new/src/actions/tests/helpers/readFixture.js
devtools/client/debugger/new/src/actions/tests/helpers/threadClient.js
devtools/client/debugger/new/src/actions/utils/middleware/log.js
devtools/client/debugger/new/src/actions/utils/middleware/timing.js
devtools/client/debugger/new/src/client/firefox/create.js
devtools/client/debugger/new/src/components/App.css
devtools/client/debugger/new/src/components/Editor/ColumnBreakpoints.css
devtools/client/debugger/new/src/components/Editor/ColumnBreakpoints.js
devtools/client/debugger/new/src/components/Editor/ConditionalPanel.css
devtools/client/debugger/new/src/components/Editor/Editor.css
devtools/client/debugger/new/src/components/Editor/EditorMenu.js
devtools/client/debugger/new/src/components/Editor/EmptyLines.js
devtools/client/debugger/new/src/components/Editor/Footer.css
devtools/client/debugger/new/src/components/Editor/Footer.js
devtools/client/debugger/new/src/components/Editor/SearchBar.css
devtools/client/debugger/new/src/components/Editor/Tabs.css
devtools/client/debugger/new/src/components/Editor/Tabs.js
devtools/client/debugger/new/src/components/Editor/index.js
devtools/client/debugger/new/src/components/Editor/menus/source.js
devtools/client/debugger/new/src/components/Editor/tests/Footer.spec.js
devtools/client/debugger/new/src/components/Editor/tests/__snapshots__/Footer.spec.js.snap
devtools/client/debugger/new/src/components/PrimaryPanes/Outline.css
devtools/client/debugger/new/src/components/PrimaryPanes/Outline.js
devtools/client/debugger/new/src/components/PrimaryPanes/Sources.css
devtools/client/debugger/new/src/components/ProjectSearch.js
devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/Breakpoint.js
devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/Breakpoints.css
devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/tests/__snapshots__/Breakpoint.spec.js.snap
devtools/client/debugger/new/src/components/SecondaryPanes/CommandBar.css
devtools/client/debugger/new/src/components/SecondaryPanes/Expressions.css
devtools/client/debugger/new/src/components/SecondaryPanes/Expressions.js
devtools/client/debugger/new/src/components/SecondaryPanes/Frames/Frame.js
devtools/client/debugger/new/src/components/SecondaryPanes/Frames/FrameIndent.js
devtools/client/debugger/new/src/components/SecondaryPanes/Frames/FrameMenu.js
devtools/client/debugger/new/src/components/SecondaryPanes/Frames/Group.js
devtools/client/debugger/new/src/components/SecondaryPanes/Frames/index.js
devtools/client/debugger/new/src/components/SecondaryPanes/Frames/tests/Frame.spec.js
devtools/client/debugger/new/src/components/SecondaryPanes/Frames/tests/FrameMenu.spec.js
devtools/client/debugger/new/src/components/SecondaryPanes/Frames/tests/Frames.spec.js
devtools/client/debugger/new/src/components/SecondaryPanes/Frames/tests/Group.spec.js
devtools/client/debugger/new/src/components/SecondaryPanes/Frames/tests/__snapshots__/Frame.spec.js.snap
devtools/client/debugger/new/src/components/SecondaryPanes/Frames/tests/__snapshots__/Frames.spec.js.snap
devtools/client/debugger/new/src/components/SecondaryPanes/Frames/tests/__snapshots__/Group.spec.js.snap
devtools/client/debugger/new/src/components/SecondaryPanes/XHRBreakpoints.js
devtools/client/debugger/new/src/components/WelcomeBox.css
devtools/client/debugger/new/src/components/WelcomeBox.js
devtools/client/debugger/new/src/components/shared/AccessibleImage.css
devtools/client/debugger/new/src/components/shared/Button/PaneToggleButton.js
devtools/client/debugger/new/src/components/shared/Button/index.js
devtools/client/debugger/new/src/components/shared/Button/styles/CommandBarButton.css
devtools/client/debugger/new/src/components/shared/Button/styles/PaneToggleButton.css
devtools/client/debugger/new/src/components/shared/Button/tests/CloseButton.spec.js
devtools/client/debugger/new/src/components/shared/Button/tests/CommandBarButton.spec.js
devtools/client/debugger/new/src/components/shared/Button/tests/PaneToggleButton.spec.js
devtools/client/debugger/new/src/components/shared/Button/tests/__snapshots__/CloseButton.spec.js.snap
devtools/client/debugger/new/src/components/shared/Button/tests/__snapshots__/PaneToggleButton.spec.js.snap
devtools/client/debugger/new/src/components/shared/ManagedTree.js
devtools/client/debugger/new/src/components/shared/PreviewFunction.js
devtools/client/debugger/new/src/components/shared/Svg.css
devtools/client/debugger/new/src/components/test/ProjectSearch.spec.js
devtools/client/debugger/new/src/components/test/__snapshots__/Outline.spec.js.snap
devtools/client/debugger/new/src/components/test/__snapshots__/ProjectSearch.spec.js.snap
devtools/client/debugger/new/src/components/test/__snapshots__/WelcomeBox.spec.js.snap
devtools/client/debugger/new/src/components/variables.css
devtools/client/debugger/new/src/reducers/async-requests.js
devtools/client/debugger/new/src/reducers/index.js
devtools/client/debugger/new/src/reducers/quick-open.js
devtools/client/debugger/new/src/reducers/tests/quick-open.spec.js
devtools/client/debugger/new/src/reducers/types.js
devtools/client/debugger/new/src/selectors/breakpointAtLocation.js
devtools/client/debugger/new/src/selectors/getCallStackFrames.js
devtools/client/debugger/new/src/selectors/isSelectedFrameVisible.js
devtools/client/debugger/new/src/selectors/visiblePausePoints.js
devtools/client/debugger/new/src/test/__mocks__/request-animation-frame.js
devtools/client/debugger/new/src/test/__mocks__/styleMock.js
devtools/client/debugger/new/src/test/__mocks__/svgMock.js
devtools/client/debugger/new/src/test/shim.js
devtools/client/debugger/new/src/test/tests-setup.js
devtools/client/debugger/new/src/test/utils/history.js
devtools/client/debugger/new/src/types.js
devtools/client/debugger/new/src/utils/bootstrap.js
devtools/client/debugger/new/src/utils/editor/source-editor.js
devtools/client/debugger/new/src/utils/editor/token-events.js
devtools/client/debugger/new/src/utils/pause/frames/collapseFrames.js
devtools/client/debugger/new/src/utils/pause/frames/displayName.js
devtools/client/debugger/new/src/utils/pause/frames/tests/displayName.spec.js
devtools/client/debugger/new/src/utils/sources-tree/sortTree.js
devtools/client/debugger/new/src/utils/tabs.js
devtools/client/debugger/new/src/utils/task.js
devtools/client/debugger/new/src/utils/test-mockup.js
devtools/client/debugger/new/src/utils/url.js
devtools/client/debugger/new/src/utils/worker.js
devtools/client/debugger/new/src/vendors.js
devtools/client/debugger/new/src/workers/parser/mapBindings.js
devtools/client/debugger/new/src/workers/parser/tests/helpers/index.js
devtools/client/debugger/new/src/workers/parser/tests/mapBindings.spec.js
devtools/client/debugger/new/src/workers/parser/tests/mapExpression.spec.js
devtools/client/debugger/new/src/workers/parser/tests/pausePoints.spec.js
devtools/client/debugger/new/src/workers/parser/utils/ast.js
devtools/client/debugger/new/src/workers/parser/utils/formatSymbols.js
devtools/client/debugger/new/src/workers/search/get-matches.js
devtools/client/debugger/new/src/workers/search/index.js
devtools/client/debugger/new/src/workers/search/project-search.js
devtools/client/debugger/new/src/workers/search/tests/project-search.spec.js
devtools/client/debugger/new/src/workers/search/worker.js
devtools/client/debugger/new/test/mochitest/browser.ini
devtools/client/debugger/new/test/mochitest/browser_dbg-expressions-focus.js
devtools/client/debugger/new/test/mochitest/browser_dbg-expressions.js
devtools/client/shared/source-map/index.js
devtools/client/shared/source-map/worker.js
--- 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 122
+Version 123
 
-Comparison: https://github.com/devtools-html/debugger.html/compare/release-121...release-122
+Comparison: https://github.com/devtools-html/debugger.html/compare/release-122...release-123
 
 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
@@ -543,16 +543,25 @@ html[dir="rtl"] .tree-node button.arrow 
   .shortcuts-section {
     width: 100%;
   }
 }
 /* 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/>. */
 
+: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 + 2px for its top and bottom borders */
+  --editor-searchbar-height: 26px;
+}
+
 :root.theme-light,
 :root .theme-light {
   --search-overlays-semitransparent: rgba(221, 225, 228, 0.66);
   --popup-shadow-color: #d0d0d0;
 }
 
 :root.theme-dark,
 :root .theme-dark {
@@ -565,42 +574,45 @@ html[dir="rtl"] .tree-node button.arrow 
 
 * {
   box-sizing: border-box;
 }
 
 button {
   background: transparent;
   border: none;
+  font-family: inherit;
+  font-size: inherit;
 }
 
 button:hover,
 button:focus {
   background-color: var(--theme-toolbar-background-hover);
 }
 
+.theme-dark button:hover,
+.theme-dark button:focus {
+  background-color: var(--theme-toolbar-hover);
+}
+
 .debugger {
   display: flex;
   flex: 1;
   height: 100%;
 }
 
 .editor-pane {
   display: flex;
   position: relative;
   flex: 1;
-  background-color: var(--theme-tab-toolbar-background);
-  height: calc(100% - 1px);
+  background-color: var(--theme-body-background);
+  height: 100%;
   overflow: hidden;
 }
 
-.theme-dark .editor-pane {
-  background-color: var(--theme-toolbar-background);
-}
-
 .editor-container {
   width: 100%;
 }
 
 .search-container {
   position: absolute;
   top: 0;
   left: 0;
@@ -1055,17 +1067,17 @@ html[dir="rtl"] .managed-tree .tree .nod
   position: fixed;
 }
 .img {
   /* default height an width which will likely be overrode */
   width: 12px;
   height: 12px;
   /* makes span appear like an image */
   display: inline-block;
-  background: var(--theme-body-color);
+  background: var(--theme-icon-color);
   mask-size: 100%;
 }
 /* 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/>. */
 
 .close-btn {
   width: 14px;
@@ -1139,68 +1151,59 @@ img.close::before {
   opacity: 0.8;
   cursor: default;
 }
 
 .command-bar-button:not(.disabled):hover {
   background: var(--theme-toolbar-background-hover);
 }
 
+.theme-dark .command-bar-button:not(.disabled):hover {
+  background: var(--theme-toolbar-hover);
+}
+
 :root.theme-dark .command-bar-button {
   color: var(--theme-body-color);
 }
 
 .command-bar-button > * {
   width: 16px;
   height: 16px;
   display: inline-block;
   vertical-align: middle;
 }
 /* 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/>. */
 
 .toggle-button {
-  transform: translate(0, 0px);
-  transition: transform 0.25s ease-in-out;
-  padding: 5px;
-  height: inherit;
+  padding: 4px 6px;
 }
 
 .toggle-button .img {
-  fill: var(--theme-comment);
-  vertical-align: 0;
-}
-
-:root.theme-dark .toggle-button .img {
-  fill: var(--theme-comment-alt);
+  vertical-align: middle;
 }
 
 .toggle-button.end {
   margin-inline-end: 0px;
   margin-inline-start: auto;
 }
 
 .toggle-button.start {
   margin-inline-start: 0px;
 }
 
-html:not([dir="rtl"]) .toggle-button.end .img,
-html[dir="rtl"] .toggle-button.start .img {
-  transform: rotate(180deg);
-}
-
-html .toggle-button.end.vertical .img {
+html[dir="rtl"] .toggle-button.start .img,
+html[dir="ltr"] .toggle-button.end:not(.vertical) .img {
+  transform: scaleX(-1);
+}
+
+.toggle-button.end.vertical .img {
   transform: rotate(-90deg);
 }
-
-.toggle-button.start.collapsed,
-.toggle-button.end.collapsed {
-  transform: rotate(180deg);
-}
 /* 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/>. */
 
 .arrow,
 .worker,
 .refresh,
 .shortcut,
@@ -1401,18 +1404,23 @@ span.img.marko {
   mask-size: 100%;
 }
 
 .img.extension {
   mask: url("resource://devtools/client/debugger/new/images/extension.svg") no-repeat;
   mask-size: 100%;
 }
 
-.img.toggle-panes {
-  mask: url("resource://devtools/client/debugger/new/images/toggle-panes.svg") no-repeat;
+.img.pane-collapse {
+  mask: url("resource://devtools/client/debugger/new/images/pane-collapse.svg") no-repeat;
+  mask-size: 100%;
+}
+
+.img.pane-expand {
+  mask: url("resource://devtools/client/debugger/new/images/pane-expand.svg") no-repeat;
   mask-size: 100%;
 }
 
 .img.file {
   mask: url("resource://devtools/client/debugger/new/images/file.svg") no-repeat;
   mask-size: 100%;
   width: 13px;
   height: 13px;
@@ -2068,17 +2076,16 @@ menuseparator {
   margin: 0;
   padding: 0 0 4px 0;
   position: absolute;
   top: 38px;
   bottom: 25px;
   left: 0;
   right: 0;
   list-style-type: none;
-  font-family: var(--monospace-font-family);
   overflow: auto;
 }
 
 .outline-list__class-list {
   margin: 0;
   padding: 0;
   list-style: none;
 }
@@ -2369,68 +2376,68 @@ menuseparator {
 .tree-indent {
   border-inline-start: 0 none;
 }
 
 .source-outline-tabs {
   font-size: 12px;
   width: 100%;
   background: var(--theme-body-background);
-  border-top: 1px solid var(--theme-splitter-color);
   display: flex;
   -moz-user-select: none;
   user-select: none;
   box-sizing: border-box;
-  height: 29px;
+  height: var(--editor-header-height);
   margin: 0;
   padding: 0;
+  border-bottom: 1px solid var(--theme-splitter-color);
 }
 
 .source-outline-tabs .tab {
+  align-items: center;
   background-color: var(--theme-toolbar-background);
-  border-top: 2px solid transparent;
-  border-bottom: 1px solid var(--theme-splitter-color);
   color: var(--theme-toolbar-color);
   cursor: default;
   display: inline-flex;
   flex: 1;
   justify-content: center;
-  margin-bottom: 0px;
-  margin-top: -1px;
   overflow: hidden;
-  padding: 5px 8px 7px 8px;
+  padding: 5px;
   position: relative;
   transition: all 0.25s ease;
 }
 
+.source-outline-tabs .tab::before {
+  content: "";
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 2px;
+  background-color: var(--tab-line-color, transparent);
+  transition: transform 250ms var(--animation-curve), opacity 250ms var(--animation-curve);
+  opacity: 0;
+  transform: scaleX(0);
+}
+
+.source-outline-tabs .tab.active {
+  --tab-line-color: var(--tab-line-selected-color);
+  color: var(--theme-toolbar-selected-color);
+  border-bottom-color: transparent;
+}
+
 .source-outline-tabs .tab:not(.active):hover {
+  --tab-line-color: var(--tab-line-hover-color);
   background-color: var(--theme-toolbar-hover);
-  border-top: 2px solid rgba(0, 0, 0, 0.2);
-}
-
-.theme-dark .source-outline-tabs .tab:hover {
-  border-top: 2px solid var(--tab-line-hover-color);
-}
-
-.source-outline-tabs .tab.active {
-  border-top: 2px solid var(--tab-line-selected-color);
-  color: var(--theme-toolbar-selected-color);
-}
-
-.theme-dark .source-outline-tabs .tab.active {
-  color: var(--theme-toolbar-selected-color);
-}
-
-.theme-dark .source-outline-tabs .tab.active:hover {
-  border-top: 2px solid var(--tab-line-selected-color);
-}
-
-.source-outline-tabs .tab.active path,
-.source-outline-tabs .tab:hover path {
-  fill: var(--theme-body-color);
+}
+
+.source-outline-tabs .tab:hover::before,
+.source-outline-tabs .tab.active::before {
+  opacity: 1;
+  transform: scaleX(1);
 }
 
 .source-outline-panel {
   flex: 1;
   overflow: auto;
 }
 
 .source-outline-panel.has-root > div {
@@ -2528,17 +2535,17 @@ menuseparator {
 
 .source-footer > .commands > .action {
   display: flex;
   justify-content: center;
   align-items: center;
   transition: opacity 200ms;
   border: none;
   background: transparent;
-  padding: 6px;
+  padding: 4px 6px;
 }
 
 .source-footer > .commands > .action .img {
   height: 100%;
   display: flex;
   flex-direction: column;
   justify-content: center;
 }
@@ -2598,23 +2605,23 @@ menuseparator {
 }
 /* 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/>. */
 
 .search-bar {
   display: flex;
   border: 1px solid transparent;
-  border-top: 1px solid var(--theme-splitter-color);
+  border-top-color: var(--theme-splitter-color);
   height: var(--editor-searchbar-height);
+  transition: border-color 200ms var(--animation-curve);
 }
 
 .search-bar.search-bar-focused {
-  border: 1px solid var(--blue-50);
-  transition: border-color 0.2s ease-in-out;
+  border-color: var(--blue-50);
 }
 
 .search-bar .search-field {
   padding-left: 7px;
 }
 
 .search-bar .search-shadow {
   flex-grow: 1;
@@ -2956,17 +2963,17 @@ menuseparator {
 }
 /* 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;
-  margin-inline-end: 4px;
+  padding-inline-end: 4px;
 }
 
 .column-breakpoint:hover {
   background-color: transparent;
 }
 
 .column-breakpoint svg {
   display: inline;
@@ -3037,30 +3044,32 @@ menuseparator {
   width: calc(100% - 4em);
   border: none;
   background: var(--theme-toolbar-background);
   font-size: 14px;
   color: var(--theme-conditional-breakpoint-color);
   line-height: 30px;
 }
 
+.conditional-breakpoint-panel input:not(:placeholder-shown) {
+  font-family: var(--monospace-font-family);
+}
+
 .conditional-breakpoint-panel input:focus {
   outline-width: 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/>. */
 
 .editor-wrapper {
   --debug-line-border: rgb(145, 188, 219);
   --debug-expression-background: rgba(202, 227, 255, 0.5);
-  --editor-searchbar-height: 27px;
   --debug-line-error-border: rgb(255, 0, 0);
   --debug-expression-error-background: rgba(231, 116, 113, 0.3);
-  --editor-header-height: 30px;
   --highlight-line-duration: 1500ms;
 }
 
 .theme-dark .editor-wrapper {
   --debug-expression-background: rgba(202, 227, 255, 0.3);
   --debug-line-border: #7786a2;
 }
 
@@ -3090,17 +3099,16 @@ menuseparator {
  * BUG https://github.com/devtools-html/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;
-  --editor-footer-height: 24px;
 }
 
 html[dir="rtl"] .editor-mount {
   direction: ltr;
 }
 
 .theme-light {
   --gutter-hover-background-color: #dde1e4;
@@ -3511,21 +3519,16 @@ html .breakpoints-list .breakpoint.pause
   color: var(--theme-comment);
   transition: color 0.15s linear;
 }
 
 .breakpoints-list .breakpoint:hover {
   background-color: var(--search-overlays-semitransparent);
 }
 
-.breakpoints-list .breakpoint .breakpoint-line,
-.breakpoints-list .breakpoint-label {
-  font-family: var(--monospace-font-family);
-}
-
 .breakpoints-list .breakpoint .breakpoint-line {
   font-size: 11px;
   color: var(--theme-comment);
   min-width: 16px;
   text-align: right;
 }
 
 html[dir="rtl"] .breakpoints-list .breakpoint .breakpoint-line {
@@ -3746,18 +3749,18 @@ html[dir="rtl"] .breakpoints-list .break
 .expression-content .tree-node {
   overflow-x: hidden;
 }
 
 .expression-content .tree-node[data-expandable="false"][aria-level="1"] {
   padding-inline-start: 10px;
 }
 
-.expression-input {
-  max-width: 50%;
+.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 [role="list"] .frames-group .group,
 .frames [role="list"] .frames-group .group .location {
   font-weight: 500;
@@ -4229,17 +4232,18 @@ html[dir="rtl"] .command-bar {
 .command-bar .active .skipPausing {
   background-color: var(--theme-highlight-blue);
 }
 
 .bottom {
   border-bottom: none;
   background-color: var(--theme-body-background);
   border-top: 1px solid var(--theme-splitter-color);
-  flex: 0 0 25px;
+  flex: none;
+  height: var(--editor-footer-height);
 }
 
 .command-bar.bottom {
   justify-content: flex-end;
 }
 
 .command-bar.bottom > button {
   color: var(--theme-comment);
@@ -4512,26 +4516,23 @@ html[dir="rtl"] .object-node {
   width: 20em;
   overflow: auto;
 }
 /* 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/>. */
 
 .welcomebox {
+  position: absolute;
+  top: var(--editor-header-height);
+  left: 0;
+  bottom: 1px;
   width: calc(100% - 1px);
-
-  /* Offsetting it by 30px for the sources-header area */
-  height: calc(100% - 30px);
-  position: absolute;
-  top: 30px;
-  left: 0;
   padding: 50px 0 0 0;
   text-align: center;
-  font-size: 1.25em;
   background-color: var(--theme-toolbar-background);
   font-weight: lighter;
   z-index: 10;
   user-select: none;
 }
 
 .theme-dark .welcomebox {
   background-color: var(--theme-body-background);
@@ -4545,16 +4546,17 @@ html[dir="rtl"] .object-node {
   offset-inline-start: auto;
   inset-inline-start: auto;
   bottom: 0;
 }
 
 .alignlabel {
   display: flex;
   white-space: nowrap;
+  font-size: 1.25em;
 }
 
 .shortcutKeys {
   font-family: Courier;
 }
 
 .shortcutKey,
 .shortcutLabel {
@@ -4605,143 +4607,98 @@ html[dir="rtl"] .object-node {
 html .welcomebox .toggle-button-end.collapsed {
   bottom: 1px;
 }
 /* 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/>. */
 
 .source-header {
-  border-bottom: 1px solid var(--theme-splitter-color);
+  display: flex;
   width: 100%;
-  height: 29px;
-  display: flex;
+  height: var(--editor-header-height);
+  border-bottom: 1px solid var(--theme-splitter-color);
+  background-color: var(--theme-toolbar-background);
 }
 
 .source-header * {
   -moz-user-select: none;
   user-select: none;
 }
 
-.source-header .new-tab-btn {
-  padding: 4px;
-  margin-top: 4px;
-  margin-left: 2px;
-  fill: var(--theme-comment);
-  transition: 0.1s ease;
-  align-self: center;
-}
-
-.source-header .new-tab-btn:hover {
-  background-color: var(--theme-toolbar-background-hover);
-}
-
-.source-header .new-tab-btn svg {
-  width: 12px;
-  display: block;
-}
-
 .source-tabs {
   max-width: calc(100% - 80px);
   align-self: flex-start;
 }
 
 .source-tab {
   display: inline-flex;
   align-items: center;
   position: relative;
   min-width: 40px;
   max-width: 100%;
   overflow: hidden;
   padding: 5px;
   cursor: default;
-  height: 30px;
+  height: calc(var(--editor-header-height) - 1px);
   font-size: 12px;
   background-color: transparent;
+  vertical-align: bottom;
 }
 
 .source-tab::before {
   content: "";
   position: absolute;
   top: 0;
   left: 0;
   width: 100%;
   height: 2px;
-  background: transparent;
+  background-color: var(--tab-line-color, transparent);
   transition: transform 250ms var(--animation-curve), opacity 250ms var(--animation-curve);
   opacity: 0;
   transform: scaleX(0);
 }
 
-.source-tab:first-child {
-  margin-inline-start: 0;
+.source-tab.active {
+  --tab-line-color: var(--tab-line-selected-color);
+  color: var(--theme-toolbar-selected-color);
+  border-bottom-color: transparent;
 }
 
 .source-tab:not(.active):hover {
-  background: linear-gradient(var(--theme-toolbar-hover) 28px, transparent 1px);
-}
-
-.source-tab:not(.active):hover::before {
-  background: var(--tab-line-hover-color);
+  --tab-line-color: var(--tab-line-hover-color);
+  background-color: var(--theme-toolbar-hover);
+}
+
+.source-tab:hover::before,
+.source-tab.active::before {
   opacity: 1;
   transform: scaleX(1);
 }
 
-.source-tab.active {
-  color: var(--theme-toolbar-selected-color);
-  border-bottom-color: transparent;
-}
-
-.source-tab.active::before {
-  background: var(--tab-line-selected-color);
-  opacity: 1;
-  transform: scaleX(1);
-}
-
-.theme-dark .source-tab.active {
-  color: var(--theme-toolbar-selected-color);
-}
-
-.source-tab.active path,
-.source-tab:hover path {
-  fill: var(--theme-body-color);
-}
-
 .source-tab .source-icon {
   margin-inline-end: 0;
 }
 
 .source-tab .img.prettyPrint,
 .source-tab .source-icon.blackBox {
   height: 12px;
   width: 12px;
   align-self: center;
 }
 
-.source-tab .prettyPrint path {
-  fill: var(--theme-textbox-box-shadow);
-}
-
 .source-tab .img.react {
   mask: url("resource://devtools/client/debugger/new/images/react.svg") no-repeat;
   mask-size: 100%;
   height: 14px;
   width: 14px;
   background: var(--theme-highlight-bluegrey);
   top: 0;
 }
 
-.source-tab .blackBox path {
-  fill: var(--theme-textbox-box-shadow);
-}
-
-.theme-dark .source-tab .blackBox circle {
-  fill: var(--theme-body-color);
-}
-
 .source-tab .filename {
   white-space: nowrap;
   text-overflow: ellipsis;
   overflow: hidden;
   padding: 0 4px;
   align-self: center;
   margin-bottom: 1px;
 }
--- a/devtools/client/debugger/new/dist/parser-worker.js
+++ b/devtools/client/debugger/new/dist/parser-worker.js
@@ -878,17 +878,17 @@ function parseVueScript(code) {
     ast = parse(code, sourceOptions.original);
   }
   return ast;
 }
 
 function parseConsoleScript(text, opts) {
   try {
     return _parse(text, {
-      plugins: ["objectRestSpread"],
+      plugins: ["objectRestSpread", "dynamicImport"],
       ...opts,
       allowAwaitOutsideFunction: true
     });
   } catch (e) {
     return null;
   }
 }
 
@@ -23125,80 +23125,103 @@ function mapOriginalExpression(expressio
 /***/ }),
 
 /***/ 3646:
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.stopSourceMapWorker = exports.startSourceMapWorker = exports.isOriginalId = exports.isGeneratedId = exports.generatedToOriginalId = exports.originalToGeneratedId = exports.getOriginalStackFrames = exports.hasMappedSource = exports.clearSourceMaps = exports.applySourceMap = exports.getOriginalSourceText = exports.getLocationScopes = exports.getFileGeneratedRange = exports.getOriginalLocation = exports.getAllGeneratedLocations = exports.getGeneratedLocation = exports.getGeneratedRanges = exports.getOriginalRanges = exports.hasOriginalURL = exports.getOriginalURLs = exports.setAssetRootURL = exports.dispatcher = undefined;
+
+var _utils = __webpack_require__(3652);
+
+Object.defineProperty(exports, "originalToGeneratedId", {
+  enumerable: true,
+  get: function () {
+    return _utils.originalToGeneratedId;
+  }
+});
+Object.defineProperty(exports, "generatedToOriginalId", {
+  enumerable: true,
+  get: function () {
+    return _utils.generatedToOriginalId;
+  }
+});
+Object.defineProperty(exports, "isGeneratedId", {
+  enumerable: true,
+  get: function () {
+    return _utils.isGeneratedId;
+  }
+});
+Object.defineProperty(exports, "isOriginalId", {
+  enumerable: true,
+  get: function () {
+    return _utils.isOriginalId;
+  }
+});
+
+var _devtoolsSourceMap = __webpack_require__(3646);
+
+var self = _interopRequireWildcard(_devtoolsSourceMap);
+
+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; } }
+
 /* 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 {
-  originalToGeneratedId,
-  generatedToOriginalId,
-  isGeneratedId,
-  isOriginalId
-} = __webpack_require__(3652);
-
-const {
   workerUtils: { WorkerDispatcher }
 } = __webpack_require__(3651);
 
-const dispatcher = new WorkerDispatcher();
-
-const setAssetRootURL = dispatcher.task("setAssetRootURL");
-const getOriginalURLs = dispatcher.task("getOriginalURLs");
-const hasOriginalURL = dispatcher.task("hasOriginalURL");
-const getOriginalRanges = dispatcher.task("getOriginalRanges");
-const getGeneratedRanges = dispatcher.task("getGeneratedRanges", {
-  queue: true
-});
-const getGeneratedLocation = dispatcher.task("getGeneratedLocation", {
-  queue: true
-});
-const getAllGeneratedLocations = dispatcher.task("getAllGeneratedLocations", {
+const dispatcher = exports.dispatcher = new WorkerDispatcher();
+
+const setAssetRootURL = exports.setAssetRootURL = async assetRoot => dispatcher.invoke("setAssetRootURL", assetRoot);
+
+const getOriginalURLs = exports.getOriginalURLs = async generatedSource => dispatcher.invoke("getOriginalURLs", generatedSource);
+
+const hasOriginalURL = exports.hasOriginalURL = async url => dispatcher.invoke("hasOriginalURL", url);
+
+const getOriginalRanges = exports.getOriginalRanges = async (sourceId, url) => dispatcher.invoke("getOriginalRanges", sourceId, url);
+
+const getGeneratedRanges = exports.getGeneratedRanges = async (location, originalSource) => dispatcher.task("getGeneratedRanges", {
   queue: true
-});
-const getOriginalLocation = dispatcher.task("getOriginalLocation");
-const getFileGeneratedRange = dispatcher.task("getFileGeneratedRange");
-const getLocationScopes = dispatcher.task("getLocationScopes");
-const getOriginalSourceText = dispatcher.task("getOriginalSourceText");
-const applySourceMap = dispatcher.task("applySourceMap");
-const clearSourceMaps = dispatcher.task("clearSourceMaps");
-const hasMappedSource = dispatcher.task("hasMappedSource");
-const getOriginalStackFrames = dispatcher.task("getOriginalStackFrames");
-
-module.exports = {
-  originalToGeneratedId,
-  generatedToOriginalId,
-  isGeneratedId,
-  isOriginalId,
-  hasMappedSource,
-  getOriginalURLs,
-  hasOriginalURL,
-  getOriginalRanges,
-  getGeneratedRanges,
-  getGeneratedLocation,
-  getAllGeneratedLocations,
-  getOriginalLocation,
-  getFileGeneratedRange,
-  getLocationScopes,
-  getOriginalSourceText,
-  applySourceMap,
-  clearSourceMaps,
-  getOriginalStackFrames,
-  startSourceMapWorker(url, assetRoot) {
-    dispatcher.start(url);
-    setAssetRootURL(assetRoot);
-  },
-  stopSourceMapWorker: dispatcher.stop.bind(dispatcher)
-};
+})(location, originalSource);
+
+const getGeneratedLocation = exports.getGeneratedLocation = async (location, originalSource) => dispatcher.task("getGeneratedLocation", { queue: true })(location, originalSource);
+
+const getAllGeneratedLocations = exports.getAllGeneratedLocations = async (location, originalSource) => dispatcher.task("getAllGeneratedLocations", { queue: true })(location, originalSource);
+
+const getOriginalLocation = exports.getOriginalLocation = async (location, options = {}) => dispatcher.invoke("getOriginalLocation", location, options);
+
+const getFileGeneratedRange = exports.getFileGeneratedRange = async originalSource => dispatcher.invoke("getFileGeneratedRange", originalSource);
+
+const getLocationScopes = exports.getLocationScopes = dispatcher.task("getLocationScopes");
+
+const getOriginalSourceText = exports.getOriginalSourceText = async originalSource => dispatcher.invoke("getOriginalSourceText", originalSource);
+
+const applySourceMap = exports.applySourceMap = async (generatedId, url, code, mappings) => dispatcher.invoke("applySourceMap", generatedId, url, code, mappings);
+
+const clearSourceMaps = exports.clearSourceMaps = async () => dispatcher.invoke("clearSourceMaps");
+
+const hasMappedSource = exports.hasMappedSource = async location => dispatcher.invoke("hasMappedSource", location);
+
+const getOriginalStackFrames = exports.getOriginalStackFrames = async generatedLocation => dispatcher.invoke("getOriginalStackFrames", generatedLocation);
+
+const startSourceMapWorker = exports.startSourceMapWorker = (url, assetRoot) => {
+  dispatcher.start(url);
+  setAssetRootURL(assetRoot);
+};
+const stopSourceMapWorker = exports.stopSourceMapWorker = dispatcher.stop.bind(dispatcher);
+
+exports.default = self;
 
 /***/ }),
 
 /***/ 3651:
 /***/ (function(module, exports, __webpack_require__) {
 
 /* 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
@@ -23646,17 +23669,17 @@ function getAssignmentTarget(node, bindi
   }
 
   return node;
 }
 
 // translates new bindings `var a = 3` into `self.a = 3`
 // and existing bindings `var a = 3` into `a = 3` for re-assignments
 function globalizeDeclaration(node, bindings) {
-  return node.declarations.map(declaration => t.expressionStatement(t.assignmentExpression("=", getAssignmentTarget(declaration.id, bindings), declaration.init)));
+  return node.declarations.map(declaration => t.expressionStatement(t.assignmentExpression("=", getAssignmentTarget(declaration.id, bindings), declaration.init || t.unaryExpression("void", t.numericLiteral(0)))));
 }
 
 // translates new bindings `a = 3` into `self.a = 3`
 // and keeps assignments the same for existing bindings.
 function globalizeAssignment(node, bindings) {
   return t.assignmentExpression(node.operator, getAssignmentTarget(node.left, bindings), node.right);
 }
 
--- a/devtools/client/debugger/new/dist/search-worker.js
+++ b/devtools/client/debugger/new/dist/search-worker.js
@@ -579,16 +579,21 @@ function getMatches(query, text, modifie
     isGlobal: true
   });
   const matchedLocations = [];
   const lines = text.split("\n");
   for (let i = 0; i < lines.length; i++) {
     let singleMatch;
     const line = lines[i];
     while ((singleMatch = regexQuery.exec(line)) !== null) {
+      // Flow doesn't understand the test above.
+      if (!singleMatch) {
+        throw new Error("no singleMatch");
+      }
+
       matchedLocations.push({ line: i, ch: singleMatch.index });
 
       // When the match is an empty string the regexQuery.lastIndex will not
       // change resulting in an infinite loop so we need to check for this and
       // increment it manually in that case.  See issue #7023
       if (singleMatch[0] === "") {
         (0, _assert2.default)(!regexQuery.unicode, "lastIndex++ can cause issues in unicode mode");
         regexQuery.lastIndex++;
@@ -614,17 +619,17 @@ exports.findSourceMatches = findSourceMa
 var _getMatches = __webpack_require__(1632);
 
 var _getMatches2 = _interopRequireDefault(_getMatches);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 function findSourceMatches(source, queryText) {
   const { id, loadedState, text } = source;
-  if (loadedState != "loaded" || !text || queryText == "") {
+  if (loadedState != "loaded" || typeof text != "string" || queryText == "") {
     return [];
   }
 
   const modifiers = {
     caseSensitive: false,
     regexMatch: false,
     wholeWord: false
   };
--- a/devtools/client/debugger/new/dist/vendors.css
+++ b/devtools/client/debugger/new/dist/vendors.css
@@ -380,18 +380,23 @@ span.img.marko {
   mask-size: 100%;
 }
 
 .img.extension {
   mask: url("resource://devtools/client/debugger/new/images/extension.svg") no-repeat;
   mask-size: 100%;
 }
 
-.img.toggle-panes {
-  mask: url("resource://devtools/client/debugger/new/images/toggle-panes.svg") no-repeat;
+.img.pane-collapse {
+  mask: url("resource://devtools/client/debugger/new/images/pane-collapse.svg") no-repeat;
+  mask-size: 100%;
+}
+
+.img.pane-expand {
+  mask: url("resource://devtools/client/debugger/new/images/pane-expand.svg") no-repeat;
   mask-size: 100%;
 }
 
 .img.file {
   mask: url("resource://devtools/client/debugger/new/images/file.svg") no-repeat;
   mask-size: 100%;
   width: 13px;
   height: 13px;
--- a/devtools/client/debugger/new/dist/vendors.js
+++ b/devtools/client/debugger/new/dist/vendors.js
@@ -947,23 +947,49 @@ module.exports = {
 /***/ }),
 
 /***/ 1464:
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
-/* 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 { formatKeyShortcut } = __webpack_require__(3786);
+var _devtoolsServices = __webpack_require__(22);
+
+var _devtoolsServices2 = _interopRequireDefault(_devtoolsServices);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+const { appinfo } = _devtoolsServices2.default; /* 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 isMacOS = appinfo.OS === "Darwin";
+
 const EventEmitter = __webpack_require__(1382);
 
+/**
+ * Formats key for use in tooltips
+ * For macOS we use the following unicode
+ *
+ * cmd ⌘ = \u2318
+ * shift ⇧ – \u21E7
+ * option (alt) ⌥ \u2325
+ *
+ * For Win/Lin this replaces CommandOrControl or CmdOrCtrl with Ctrl
+ *
+ * @static
+ */
+function formatKeyShortcut(shortcut) {
+  if (isMacOS) {
+    return shortcut.replace(/Shift\+/g, "\u21E7").replace(/Command\+|Cmd\+/g, "\u2318").replace(/CommandOrControl\+|CmdOrCtrl\+/g, "\u2318").replace(/Alt\+/g, "\u2325");
+  }
+  return shortcut.replace(/CommandOrControl\+|CmdOrCtrl\+/g, `${L10N.getStr("ctrl")}+`).replace(/Shift\+/g, "Shift+");
+}
+
 function inToolbox() {
   try {
     return window.parent.document.documentURI == "about:devtools-toolbox";
   } catch (e) {
     // If `window` is not available, it's very likely that we are in the toolbox.
     return true;
   }
 }
@@ -3865,17 +3891,17 @@ module.exports = {
 // should implement the similar functionalities on its own.
 //
 // Please keep in mind that if the feature in this file has changed, don't
 // forget to also change that accordingly in
 // devtools/client/shared/unicode-url.js in the mozilla-central repository.
 
 
 
-const punycode = __webpack_require__(916);
+const punycode = __webpack_require__(3641);
 
 /**
  * Gets a readble Unicode hostname from a hostname.
  *
  * If the `hostname` is a readable ASCII hostname, such as example.org, then
  * this function will simply return the original `hostname`.
  *
  * If the `hostname` is a Punycode hostname representing a Unicode domain name,
@@ -3964,16 +3990,556 @@ function getUnicodeUrl(url) {
 module.exports = {
   getUnicodeHostname,
   getUnicodeUrlPath,
   getUnicodeUrl
 };
 
 /***/ }),
 
+/***/ 3641:
+/***/ (function(module, exports, __webpack_require__) {
+
+/* WEBPACK VAR INJECTION */(function(module, global) {var __WEBPACK_AMD_DEFINE_RESULT__;/*! https://mths.be/punycode v1.4.1 by @mathias */
+;(function(root) {
+
+	/** Detect free variables */
+	var freeExports = typeof exports == 'object' && exports &&
+		!exports.nodeType && exports;
+	var freeModule = typeof module == 'object' && module &&
+		!module.nodeType && module;
+	var freeGlobal = typeof global == 'object' && global;
+	if (
+		freeGlobal.global === freeGlobal ||
+		freeGlobal.window === freeGlobal ||
+		freeGlobal.self === freeGlobal
+	) {
+		root = freeGlobal;
+	}
+
+	/**
+	 * The `punycode` object.
+	 * @name punycode
+	 * @type Object
+	 */
+	var punycode,
+
+	/** Highest positive signed 32-bit float value */
+	maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
+
+	/** Bootstring parameters */
+	base = 36,
+	tMin = 1,
+	tMax = 26,
+	skew = 38,
+	damp = 700,
+	initialBias = 72,
+	initialN = 128, // 0x80
+	delimiter = '-', // '\x2D'
+
+	/** Regular expressions */
+	regexPunycode = /^xn--/,
+	regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
+	regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
+
+	/** Error messages */
+	errors = {
+		'overflow': 'Overflow: input needs wider integers to process',
+		'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
+		'invalid-input': 'Invalid input'
+	},
+
+	/** Convenience shortcuts */
+	baseMinusTMin = base - tMin,
+	floor = Math.floor,
+	stringFromCharCode = String.fromCharCode,
+
+	/** Temporary variable */
+	key;
+
+	/*--------------------------------------------------------------------------*/
+
+	/**
+	 * A generic error utility function.
+	 * @private
+	 * @param {String} type The error type.
+	 * @returns {Error} Throws a `RangeError` with the applicable error message.
+	 */
+	function error(type) {
+		throw new RangeError(errors[type]);
+	}
+
+	/**
+	 * A generic `Array#map` utility function.
+	 * @private
+	 * @param {Array} array The array to iterate over.
+	 * @param {Function} callback The function that gets called for every array
+	 * item.
+	 * @returns {Array} A new array of values returned by the callback function.
+	 */
+	function map(array, fn) {
+		var length = array.length;
+		var result = [];
+		while (length--) {
+			result[length] = fn(array[length]);
+		}
+		return result;
+	}
+
+	/**
+	 * A simple `Array#map`-like wrapper to work with domain name strings or email
+	 * addresses.
+	 * @private
+	 * @param {String} domain The domain name or email address.
+	 * @param {Function} callback The function that gets called for every
+	 * character.
+	 * @returns {Array} A new string of characters returned by the callback
+	 * function.
+	 */
+	function mapDomain(string, fn) {
+		var parts = string.split('@');
+		var result = '';
+		if (parts.length > 1) {
+			// In email addresses, only the domain name should be punycoded. Leave
+			// the local part (i.e. everything up to `@`) intact.
+			result = parts[0] + '@';
+			string = parts[1];
+		}
+		// Avoid `split(regex)` for IE8 compatibility. See #17.
+		string = string.replace(regexSeparators, '\x2E');
+		var labels = string.split('.');
+		var encoded = map(labels, fn).join('.');
+		return result + encoded;
+	}
+
+	/**
+	 * Creates an array containing the numeric code points of each Unicode
+	 * character in the string. While JavaScript uses UCS-2 internally,
+	 * this function will convert a pair of surrogate halves (each of which
+	 * UCS-2 exposes as separate characters) into a single code point,
+	 * matching UTF-16.
+	 * @see `punycode.ucs2.encode`
+	 * @see <https://mathiasbynens.be/notes/javascript-encoding>
+	 * @memberOf punycode.ucs2
+	 * @name decode
+	 * @param {String} string The Unicode input string (UCS-2).
+	 * @returns {Array} The new array of code points.
+	 */
+	function ucs2decode(string) {
+		var output = [],
+		    counter = 0,
+		    length = string.length,
+		    value,
+		    extra;
+		while (counter < length) {
+			value = string.charCodeAt(counter++);
+			if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
+				// high surrogate, and there is a next character
+				extra = string.charCodeAt(counter++);
+				if ((extra & 0xFC00) == 0xDC00) { // low surrogate
+					output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
+				} else {
+					// unmatched surrogate; only append this code unit, in case the next
+					// code unit is the high surrogate of a surrogate pair
+					output.push(value);
+					counter--;
+				}
+			} else {
+				output.push(value);
+			}
+		}
+		return output;
+	}
+
+	/**
+	 * Creates a string based on an array of numeric code points.
+	 * @see `punycode.ucs2.decode`
+	 * @memberOf punycode.ucs2
+	 * @name encode
+	 * @param {Array} codePoints The array of numeric code points.
+	 * @returns {String} The new Unicode string (UCS-2).
+	 */
+	function ucs2encode(array) {
+		return map(array, function(value) {
+			var output = '';
+			if (value > 0xFFFF) {
+				value -= 0x10000;
+				output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
+				value = 0xDC00 | value & 0x3FF;
+			}
+			output += stringFromCharCode(value);
+			return output;
+		}).join('');
+	}
+
+	/**
+	 * Converts a basic code point into a digit/integer.
+	 * @see `digitToBasic()`
+	 * @private
+	 * @param {Number} codePoint The basic numeric code point value.
+	 * @returns {Number} The numeric value of a basic code point (for use in
+	 * representing integers) in the range `0` to `base - 1`, or `base` if
+	 * the code point does not represent a value.
+	 */
+	function basicToDigit(codePoint) {
+		if (codePoint - 48 < 10) {
+			return codePoint - 22;
+		}
+		if (codePoint - 65 < 26) {
+			return codePoint - 65;
+		}
+		if (codePoint - 97 < 26) {
+			return codePoint - 97;
+		}
+		return base;
+	}
+
+	/**
+	 * Converts a digit/integer into a basic code point.
+	 * @see `basicToDigit()`
+	 * @private
+	 * @param {Number} digit The numeric value of a basic code point.
+	 * @returns {Number} The basic code point whose value (when used for
+	 * representing integers) is `digit`, which needs to be in the range
+	 * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
+	 * used; else, the lowercase form is used. The behavior is undefined
+	 * if `flag` is non-zero and `digit` has no uppercase form.
+	 */
+	function digitToBasic(digit, flag) {
+		//  0..25 map to ASCII a..z or A..Z
+		// 26..35 map to ASCII 0..9
+		return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
+	}
+
+	/**
+	 * Bias adaptation function as per section 3.4 of RFC 3492.
+	 * https://tools.ietf.org/html/rfc3492#section-3.4
+	 * @private
+	 */
+	function adapt(delta, numPoints, firstTime) {
+		var k = 0;
+		delta = firstTime ? floor(delta / damp) : delta >> 1;
+		delta += floor(delta / numPoints);
+		for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
+			delta = floor(delta / baseMinusTMin);
+		}
+		return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
+	}
+
+	/**
+	 * Converts a Punycode string of ASCII-only symbols to a string of Unicode
+	 * symbols.
+	 * @memberOf punycode
+	 * @param {String} input The Punycode string of ASCII-only symbols.
+	 * @returns {String} The resulting string of Unicode symbols.
+	 */
+	function decode(input) {
+		// Don't use UCS-2
+		var output = [],
+		    inputLength = input.length,
+		    out,
+		    i = 0,
+		    n = initialN,
+		    bias = initialBias,
+		    basic,
+		    j,
+		    index,
+		    oldi,
+		    w,
+		    k,
+		    digit,
+		    t,
+		    /** Cached calculation results */
+		    baseMinusT;
+
+		// Handle the basic code points: let `basic` be the number of input code
+		// points before the last delimiter, or `0` if there is none, then copy
+		// the first basic code points to the output.
+
+		basic = input.lastIndexOf(delimiter);
+		if (basic < 0) {
+			basic = 0;
+		}
+
+		for (j = 0; j < basic; ++j) {
+			// if it's not a basic code point
+			if (input.charCodeAt(j) >= 0x80) {
+				error('not-basic');
+			}
+			output.push(input.charCodeAt(j));
+		}
+
+		// Main decoding loop: start just after the last delimiter if any basic code
+		// points were copied; start at the beginning otherwise.
+
+		for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
+
+			// `index` is the index of the next character to be consumed.
+			// Decode a generalized variable-length integer into `delta`,
+			// which gets added to `i`. The overflow checking is easier
+			// if we increase `i` as we go, then subtract off its starting
+			// value at the end to obtain `delta`.
+			for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
+
+				if (index >= inputLength) {
+					error('invalid-input');
+				}
+
+				digit = basicToDigit(input.charCodeAt(index++));
+
+				if (digit >= base || digit > floor((maxInt - i) / w)) {
+					error('overflow');
+				}
+
+				i += digit * w;
+				t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+
+				if (digit < t) {
+					break;
+				}
+
+				baseMinusT = base - t;
+				if (w > floor(maxInt / baseMinusT)) {
+					error('overflow');
+				}
+
+				w *= baseMinusT;
+
+			}
+
+			out = output.length + 1;
+			bias = adapt(i - oldi, out, oldi == 0);
+
+			// `i` was supposed to wrap around from `out` to `0`,
+			// incrementing `n` each time, so we'll fix that now:
+			if (floor(i / out) > maxInt - n) {
+				error('overflow');
+			}
+
+			n += floor(i / out);
+			i %= out;
+
+			// Insert `n` at position `i` of the output
+			output.splice(i++, 0, n);
+
+		}
+
+		return ucs2encode(output);
+	}
+
+	/**
+	 * Converts a string of Unicode symbols (e.g. a domain name label) to a
+	 * Punycode string of ASCII-only symbols.
+	 * @memberOf punycode
+	 * @param {String} input The string of Unicode symbols.
+	 * @returns {String} The resulting Punycode string of ASCII-only symbols.
+	 */
+	function encode(input) {
+		var n,
+		    delta,
+		    handledCPCount,
+		    basicLength,
+		    bias,
+		    j,
+		    m,
+		    q,
+		    k,
+		    t,
+		    currentValue,
+		    output = [],
+		    /** `inputLength` will hold the number of code points in `input`. */
+		    inputLength,
+		    /** Cached calculation results */
+		    handledCPCountPlusOne,
+		    baseMinusT,
+		    qMinusT;
+
+		// Convert the input in UCS-2 to Unicode
+		input = ucs2decode(input);
+
+		// Cache the length
+		inputLength = input.length;
+
+		// Initialize the state
+		n = initialN;
+		delta = 0;
+		bias = initialBias;
+
+		// Handle the basic code points
+		for (j = 0; j < inputLength; ++j) {
+			currentValue = input[j];
+			if (currentValue < 0x80) {
+				output.push(stringFromCharCode(currentValue));
+			}
+		}
+
+		handledCPCount = basicLength = output.length;
+
+		// `handledCPCount` is the number of code points that have been handled;
+		// `basicLength` is the number of basic code points.
+
+		// Finish the basic string - if it is not empty - with a delimiter
+		if (basicLength) {
+			output.push(delimiter);
+		}
+
+		// Main encoding loop:
+		while (handledCPCount < inputLength) {
+
+			// All non-basic code points < n have been handled already. Find the next
+			// larger one:
+			for (m = maxInt, j = 0; j < inputLength; ++j) {
+				currentValue = input[j];
+				if (currentValue >= n && currentValue < m) {
+					m = currentValue;
+				}
+			}
+
+			// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
+			// but guard against overflow
+			handledCPCountPlusOne = handledCPCount + 1;
+			if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
+				error('overflow');
+			}
+
+			delta += (m - n) * handledCPCountPlusOne;
+			n = m;
+
+			for (j = 0; j < inputLength; ++j) {
+				currentValue = input[j];
+
+				if (currentValue < n && ++delta > maxInt) {
+					error('overflow');
+				}
+
+				if (currentValue == n) {
+					// Represent delta as a generalized variable-length integer
+					for (q = delta, k = base; /* no condition */; k += base) {
+						t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+						if (q < t) {
+							break;
+						}
+						qMinusT = q - t;
+						baseMinusT = base - t;
+						output.push(
+							stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
+						);
+						q = floor(qMinusT / baseMinusT);
+					}
+
+					output.push(stringFromCharCode(digitToBasic(q, 0)));
+					bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
+					delta = 0;
+					++handledCPCount;
+				}
+			}
+
+			++delta;
+			++n;
+
+		}
+		return output.join('');
+	}
+
+	/**
+	 * Converts a Punycode string representing a domain name or an email address
+	 * to Unicode. Only the Punycoded parts of the input will be converted, i.e.
+	 * it doesn't matter if you call it on a string that has already been
+	 * converted to Unicode.
+	 * @memberOf punycode
+	 * @param {String} input The Punycoded domain name or email address to
+	 * convert to Unicode.
+	 * @returns {String} The Unicode representation of the given Punycode
+	 * string.
+	 */
+	function toUnicode(input) {
+		return mapDomain(input, function(string) {
+			return regexPunycode.test(string)
+				? decode(string.slice(4).toLowerCase())
+				: string;
+		});
+	}
+
+	/**
+	 * Converts a Unicode string representing a domain name or an email address to
+	 * Punycode. Only the non-ASCII parts of the domain name will be converted,
+	 * i.e. it doesn't matter if you call it with a domain that's already in
+	 * ASCII.
+	 * @memberOf punycode
+	 * @param {String} input The domain name or email address to convert, as a
+	 * Unicode string.
+	 * @returns {String} The Punycode representation of the given domain name or
+	 * email address.
+	 */
+	function toASCII(input) {
+		return mapDomain(input, function(string) {
+			return regexNonASCII.test(string)
+				? 'xn--' + encode(string)
+				: string;
+		});
+	}
+
+	/*--------------------------------------------------------------------------*/
+
+	/** Define the public API */
+	punycode = {
+		/**
+		 * A string representing the current Punycode.js version number.
+		 * @memberOf punycode
+		 * @type String
+		 */
+		'version': '1.4.1',
+		/**
+		 * An object of methods to convert from JavaScript's internal character
+		 * representation (UCS-2) to Unicode code points, and back.
+		 * @see <https://mathiasbynens.be/notes/javascript-encoding>
+		 * @memberOf punycode
+		 * @type Object
+		 */
+		'ucs2': {
+			'decode': ucs2decode,
+			'encode': ucs2encode
+		},
+		'decode': decode,
+		'encode': encode,
+		'toASCII': toASCII,
+		'toUnicode': toUnicode
+	};
+
+	/** Expose `punycode` */
+	// Some AMD build optimizers, like r.js, check for specific condition patterns
+	// like the following:
+	if (
+		true
+	) {
+		!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {
+			return punycode;
+		}).call(exports, __webpack_require__, exports, module),
+				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+	} else if (freeExports && freeModule) {
+		if (module.exports == freeExports) {
+			// in Node.js, io.js, or RingoJS v0.8.0+
+			freeModule.exports = punycode;
+		} else {
+			// in Narwhal or RingoJS v0.7.0-
+			for (key in punycode) {
+				punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
+			}
+		}
+	} else {
+		// in Rhino or a web browser
+		root.punycode = punycode;
+	}
+
+}(this));
+
+/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(793)(module), __webpack_require__(792)))
+
+/***/ }),
+
 /***/ 3642:
 /***/ (function(module, exports) {
 
 module.exports = __WEBPACK_EXTERNAL_MODULE_3642__;
 
 /***/ }),
 
 /***/ 3643:
@@ -5233,16 +5799,17 @@ const vendored = exports.vendored = {
   "lodash-move": _lodashMove2.default,
   "react-aria-components/src/tabs": reactAriaComponentsTabs,
   "react-transition-group/Transition": transition,
   reselect,
   // Svg is required via relative paths, so the key is not imported path.
   // See .babel/transform-mc.js
   Svg: _Svg2.default
 };
+// $FlowIgnore
 
 /***/ }),
 
 /***/ 3750:
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
@@ -6475,67 +7042,16 @@ var _propTypes = __webpack_require__(364
 var _propTypes2 = _interopRequireDefault(_propTypes);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 exports.default = _propTypes2.default.object;
 
 /***/ }),
 
-/***/ 3786:
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
-  value: true
-});
-exports.formatKeyShortcut = formatKeyShortcut;
-
-var _devtoolsServices = __webpack_require__(22);
-
-var _devtoolsServices2 = _interopRequireDefault(_devtoolsServices);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-const { appinfo } = _devtoolsServices2.default; /* 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/>. */
-
-/**
- * Utils for keyboard command strings
- * @module utils/text
- */
-
-
-const isMacOS = appinfo.OS === "Darwin";
-
-/**
- * Formats key for use in tooltips
- * For macOS we use the following unicode
- *
- * cmd ⌘ = \u2318
- * shift ⇧ – \u21E7
- * option (alt) ⌥ \u2325
- *
- * For Win/Lin this replaces CommandOrControl or CmdOrCtrl with Ctrl
- *
- * @memberof utils/text
- * @static
- */
-function formatKeyShortcut(shortcut) {
-  if (isMacOS) {
-    return shortcut.replace(/Shift\+/g, "\u21E7").replace(/Command\+|Cmd\+/g, "\u2318").replace(/CommandOrControl\+|CmdOrCtrl\+/g, "\u2318").replace(/Alt\+/g, "\u2325");
-  }
-  return shortcut.replace(/CommandOrControl\+|CmdOrCtrl\+/g, "Ctrl").replace(/Shift\+/g, "Shift");
-}
-
-/***/ }),
-
 /***/ 3791:
 /***/ (function(module, __webpack_exports__, __webpack_require__) {
 
 "use strict";
 Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
 /* harmony export (immutable) */ __webpack_exports__["defaultMemoize"] = defaultMemoize;
 /* harmony export (immutable) */ __webpack_exports__["createSelectorCreator"] = createSelectorCreator;
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createSelector", function() { return createSelector; });
@@ -7148,552 +7664,12 @@ module.exports = function(module) {
 			}
 		});
 		module.webpackPolyfill = 1;
 	}
 	return module;
 };
 
 
-/***/ }),
-
-/***/ 916:
-/***/ (function(module, exports, __webpack_require__) {
-
-/* WEBPACK VAR INJECTION */(function(module, global) {var __WEBPACK_AMD_DEFINE_RESULT__;/*! https://mths.be/punycode v1.4.1 by @mathias */
-;(function(root) {
-
-	/** Detect free variables */
-	var freeExports = typeof exports == 'object' && exports &&
-		!exports.nodeType && exports;
-	var freeModule = typeof module == 'object' && module &&
-		!module.nodeType && module;
-	var freeGlobal = typeof global == 'object' && global;
-	if (
-		freeGlobal.global === freeGlobal ||
-		freeGlobal.window === freeGlobal ||
-		freeGlobal.self === freeGlobal
-	) {
-		root = freeGlobal;
-	}
-
-	/**
-	 * The `punycode` object.
-	 * @name punycode
-	 * @type Object
-	 */
-	var punycode,
-
-	/** Highest positive signed 32-bit float value */
-	maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
-
-	/** Bootstring parameters */
-	base = 36,
-	tMin = 1,
-	tMax = 26,
-	skew = 38,
-	damp = 700,
-	initialBias = 72,
-	initialN = 128, // 0x80
-	delimiter = '-', // '\x2D'
-
-	/** Regular expressions */
-	regexPunycode = /^xn--/,
-	regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
-	regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
-
-	/** Error messages */
-	errors = {
-		'overflow': 'Overflow: input needs wider integers to process',
-		'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
-		'invalid-input': 'Invalid input'
-	},
-
-	/** Convenience shortcuts */
-	baseMinusTMin = base - tMin,
-	floor = Math.floor,
-	stringFromCharCode = String.fromCharCode,
-
-	/** Temporary variable */
-	key;
-
-	/*--------------------------------------------------------------------------*/
-
-	/**
-	 * A generic error utility function.
-	 * @private
-	 * @param {String} type The error type.
-	 * @returns {Error} Throws a `RangeError` with the applicable error message.
-	 */
-	function error(type) {
-		throw new RangeError(errors[type]);
-	}
-
-	/**
-	 * A generic `Array#map` utility function.
-	 * @private
-	 * @param {Array} array The array to iterate over.
-	 * @param {Function} callback The function that gets called for every array
-	 * item.
-	 * @returns {Array} A new array of values returned by the callback function.
-	 */
-	function map(array, fn) {
-		var length = array.length;
-		var result = [];
-		while (length--) {
-			result[length] = fn(array[length]);
-		}
-		return result;
-	}
-
-	/**
-	 * A simple `Array#map`-like wrapper to work with domain name strings or email
-	 * addresses.
-	 * @private
-	 * @param {String} domain The domain name or email address.
-	 * @param {Function} callback The function that gets called for every
-	 * character.
-	 * @returns {Array} A new string of characters returned by the callback
-	 * function.
-	 */
-	function mapDomain(string, fn) {
-		var parts = string.split('@');
-		var result = '';
-		if (parts.length > 1) {
-			// In email addresses, only the domain name should be punycoded. Leave
-			// the local part (i.e. everything up to `@`) intact.
-			result = parts[0] + '@';
-			string = parts[1];
-		}
-		// Avoid `split(regex)` for IE8 compatibility. See #17.
-		string = string.replace(regexSeparators, '\x2E');
-		var labels = string.split('.');
-		var encoded = map(labels, fn).join('.');
-		return result + encoded;
-	}
-
-	/**
-	 * Creates an array containing the numeric code points of each Unicode
-	 * character in the string. While JavaScript uses UCS-2 internally,
-	 * this function will convert a pair of surrogate halves (each of which
-	 * UCS-2 exposes as separate characters) into a single code point,
-	 * matching UTF-16.
-	 * @see `punycode.ucs2.encode`
-	 * @see <https://mathiasbynens.be/notes/javascript-encoding>
-	 * @memberOf punycode.ucs2
-	 * @name decode
-	 * @param {String} string The Unicode input string (UCS-2).
-	 * @returns {Array} The new array of code points.
-	 */
-	function ucs2decode(string) {
-		var output = [],
-		    counter = 0,
-		    length = string.length,
-		    value,
-		    extra;
-		while (counter < length) {
-			value = string.charCodeAt(counter++);
-			if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
-				// high surrogate, and there is a next character
-				extra = string.charCodeAt(counter++);
-				if ((extra & 0xFC00) == 0xDC00) { // low surrogate
-					output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
-				} else {
-					// unmatched surrogate; only append this code unit, in case the next
-					// code unit is the high surrogate of a surrogate pair
-					output.push(value);
-					counter--;
-				}
-			} else {
-				output.push(value);
-			}
-		}
-		return output;
-	}
-
-	/**
-	 * Creates a string based on an array of numeric code points.
-	 * @see `punycode.ucs2.decode`
-	 * @memberOf punycode.ucs2
-	 * @name encode
-	 * @param {Array} codePoints The array of numeric code points.
-	 * @returns {String} The new Unicode string (UCS-2).
-	 */
-	function ucs2encode(array) {
-		return map(array, function(value) {
-			var output = '';
-			if (value > 0xFFFF) {
-				value -= 0x10000;
-				output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
-				value = 0xDC00 | value & 0x3FF;
-			}
-			output += stringFromCharCode(value);
-			return output;
-		}).join('');
-	}
-
-	/**
-	 * Converts a basic code point into a digit/integer.
-	 * @see `digitToBasic()`
-	 * @private
-	 * @param {Number} codePoint The basic numeric code point value.
-	 * @returns {Number} The numeric value of a basic code point (for use in
-	 * representing integers) in the range `0` to `base - 1`, or `base` if
-	 * the code point does not represent a value.
-	 */
-	function basicToDigit(codePoint) {
-		if (codePoint - 48 < 10) {
-			return codePoint - 22;
-		}
-		if (codePoint - 65 < 26) {
-			return codePoint - 65;
-		}
-		if (codePoint - 97 < 26) {
-			return codePoint - 97;
-		}
-		return base;
-	}
-
-	/**
-	 * Converts a digit/integer into a basic code point.
-	 * @see `basicToDigit()`
-	 * @private
-	 * @param {Number} digit The numeric value of a basic code point.
-	 * @returns {Number} The basic code point whose value (when used for
-	 * representing integers) is `digit`, which needs to be in the range
-	 * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
-	 * used; else, the lowercase form is used. The behavior is undefined
-	 * if `flag` is non-zero and `digit` has no uppercase form.
-	 */
-	function digitToBasic(digit, flag) {
-		//  0..25 map to ASCII a..z or A..Z
-		// 26..35 map to ASCII 0..9
-		return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
-	}
-
-	/**
-	 * Bias adaptation function as per section 3.4 of RFC 3492.
-	 * https://tools.ietf.org/html/rfc3492#section-3.4
-	 * @private
-	 */
-	function adapt(delta, numPoints, firstTime) {
-		var k = 0;
-		delta = firstTime ? floor(delta / damp) : delta >> 1;
-		delta += floor(delta / numPoints);
-		for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
-			delta = floor(delta / baseMinusTMin);
-		}
-		return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
-	}
-
-	/**
-	 * Converts a Punycode string of ASCII-only symbols to a string of Unicode
-	 * symbols.
-	 * @memberOf punycode
-	 * @param {String} input The Punycode string of ASCII-only symbols.
-	 * @returns {String} The resulting string of Unicode symbols.
-	 */
-	function decode(input) {
-		// Don't use UCS-2
-		var output = [],
-		    inputLength = input.length,
-		    out,
-		    i = 0,
-		    n = initialN,
-		    bias = initialBias,
-		    basic,
-		    j,
-		    index,
-		    oldi,
-		    w,
-		    k,
-		    digit,
-		    t,
-		    /** Cached calculation results */
-		    baseMinusT;
-
-		// Handle the basic code points: let `basic` be the number of input code
-		// points before the last delimiter, or `0` if there is none, then copy
-		// the first basic code points to the output.
-
-		basic = input.lastIndexOf(delimiter);
-		if (basic < 0) {
-			basic = 0;
-		}
-
-		for (j = 0; j < basic; ++j) {
-			// if it's not a basic code point
-			if (input.charCodeAt(j) >= 0x80) {
-				error('not-basic');
-			}
-			output.push(input.charCodeAt(j));
-		}
-
-		// Main decoding loop: start just after the last delimiter if any basic code
-		// points were copied; start at the beginning otherwise.
-
-		for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
-
-			// `index` is the index of the next character to be consumed.
-			// Decode a generalized variable-length integer into `delta`,
-			// which gets added to `i`. The overflow checking is easier
-			// if we increase `i` as we go, then subtract off its starting
-			// value at the end to obtain `delta`.
-			for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
-
-				if (index >= inputLength) {
-					error('invalid-input');
-				}
-
-				digit = basicToDigit(input.charCodeAt(index++));
-
-				if (digit >= base || digit > floor((maxInt - i) / w)) {
-					error('overflow');
-				}
-
-				i += digit * w;
-				t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
-
-				if (digit < t) {
-					break;
-				}
-
-				baseMinusT = base - t;
-				if (w > floor(maxInt / baseMinusT)) {
-					error('overflow');
-				}
-
-				w *= baseMinusT;
-
-			}
-
-			out = output.length + 1;
-			bias = adapt(i - oldi, out, oldi == 0);
-
-			// `i` was supposed to wrap around from `out` to `0`,
-			// incrementing `n` each time, so we'll fix that now:
-			if (floor(i / out) > maxInt - n) {
-				error('overflow');
-			}
-
-			n += floor(i / out);
-			i %= out;
-
-			// Insert `n` at position `i` of the output
-			output.splice(i++, 0, n);
-
-		}
-
-		return ucs2encode(output);
-	}
-
-	/**
-	 * Converts a string of Unicode symbols (e.g. a domain name label) to a
-	 * Punycode string of ASCII-only symbols.
-	 * @memberOf punycode
-	 * @param {String} input The string of Unicode symbols.
-	 * @returns {String} The resulting Punycode string of ASCII-only symbols.
-	 */
-	function encode(input) {
-		var n,
-		    delta,
-		    handledCPCount,
-		    basicLength,
-		    bias,
-		    j,
-		    m,
-		    q,
-		    k,
-		    t,
-		    currentValue,
-		    output = [],
-		    /** `inputLength` will hold the number of code points in `input`. */
-		    inputLength,
-		    /** Cached calculation results */
-		    handledCPCountPlusOne,
-		    baseMinusT,
-		    qMinusT;
-
-		// Convert the input in UCS-2 to Unicode
-		input = ucs2decode(input);
-
-		// Cache the length
-		inputLength = input.length;
-
-		// Initialize the state
-		n = initialN;
-		delta = 0;
-		bias = initialBias;
-
-		// Handle the basic code points
-		for (j = 0; j < inputLength; ++j) {
-			currentValue = input[j];
-			if (currentValue < 0x80) {
-				output.push(stringFromCharCode(currentValue));
-			}
-		}
-
-		handledCPCount = basicLength = output.length;
-
-		// `handledCPCount` is the number of code points that have been handled;
-		// `basicLength` is the number of basic code points.
-
-		// Finish the basic string - if it is not empty - with a delimiter
-		if (basicLength) {
-			output.push(delimiter);
-		}
-
-		// Main encoding loop:
-		while (handledCPCount < inputLength) {
-
-			// All non-basic code points < n have been handled already. Find the next
-			// larger one:
-			for (m = maxInt, j = 0; j < inputLength; ++j) {
-				currentValue = input[j];
-				if (currentValue >= n && currentValue < m) {
-					m = currentValue;
-				}
-			}
-
-			// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
-			// but guard against overflow
-			handledCPCountPlusOne = handledCPCount + 1;
-			if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
-				error('overflow');
-			}
-
-			delta += (m - n) * handledCPCountPlusOne;
-			n = m;
-
-			for (j = 0; j < inputLength; ++j) {
-				currentValue = input[j];
-
-				if (currentValue < n && ++delta > maxInt) {
-					error('overflow');
-				}
-
-				if (currentValue == n) {
-					// Represent delta as a generalized variable-length integer
-					for (q = delta, k = base; /* no condition */; k += base) {
-						t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
-						if (q < t) {
-							break;
-						}
-						qMinusT = q - t;
-						baseMinusT = base - t;
-						output.push(
-							stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
-						);
-						q = floor(qMinusT / baseMinusT);
-					}
-
-					output.push(stringFromCharCode(digitToBasic(q, 0)));
-					bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
-					delta = 0;
-					++handledCPCount;
-				}
-			}
-
-			++delta;
-			++n;
-
-		}
-		return output.join('');
-	}
-
-	/**
-	 * Converts a Punycode string representing a domain name or an email address
-	 * to Unicode. Only the Punycoded parts of the input will be converted, i.e.
-	 * it doesn't matter if you call it on a string that has already been
-	 * converted to Unicode.
-	 * @memberOf punycode
-	 * @param {String} input The Punycoded domain name or email address to
-	 * convert to Unicode.
-	 * @returns {String} The Unicode representation of the given Punycode
-	 * string.
-	 */
-	function toUnicode(input) {
-		return mapDomain(input, function(string) {
-			return regexPunycode.test(string)
-				? decode(string.slice(4).toLowerCase())
-				: string;
-		});
-	}
-
-	/**
-	 * Converts a Unicode string representing a domain name or an email address to
-	 * Punycode. Only the non-ASCII parts of the domain name will be converted,
-	 * i.e. it doesn't matter if you call it with a domain that's already in
-	 * ASCII.
-	 * @memberOf punycode
-	 * @param {String} input The domain name or email address to convert, as a
-	 * Unicode string.
-	 * @returns {String} The Punycode representation of the given domain name or
-	 * email address.
-	 */
-	function toASCII(input) {
-		return mapDomain(input, function(string) {
-			return regexNonASCII.test(string)
-				? 'xn--' + encode(string)
-				: string;
-		});
-	}
-
-	/*--------------------------------------------------------------------------*/
-
-	/** Define the public API */
-	punycode = {
-		/**
-		 * A string representing the current Punycode.js version number.
-		 * @memberOf punycode
-		 * @type String
-		 */
-		'version': '1.4.1',
-		/**
-		 * An object of methods to convert from JavaScript's internal character
-		 * representation (UCS-2) to Unicode code points, and back.
-		 * @see <https://mathiasbynens.be/notes/javascript-encoding>
-		 * @memberOf punycode
-		 * @type Object
-		 */
-		'ucs2': {
-			'decode': ucs2decode,
-			'encode': ucs2encode
-		},
-		'decode': decode,
-		'encode': encode,
-		'toASCII': toASCII,
-		'toUnicode': toUnicode
-	};
-
-	/** Expose `punycode` */
-	// Some AMD build optimizers, like r.js, check for specific condition patterns
-	// like the following:
-	if (
-		true
-	) {
-		!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {
-			return punycode;
-		}).call(exports, __webpack_require__, exports, module),
-				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
-	} else if (freeExports && freeModule) {
-		if (module.exports == freeExports) {
-			// in Node.js, io.js, or RingoJS v0.8.0+
-			freeModule.exports = punycode;
-		} else {
-			// in Narwhal or RingoJS v0.7.0-
-			for (key in punycode) {
-				punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
-			}
-		}
-	} else {
-		// in Rhino or a web browser
-		root.punycode = punycode;
-	}
-
-}(this));
-
-/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(793)(module), __webpack_require__(792)))
-
 /***/ })
 
 /******/ });
 });
\ No newline at end of file
--- a/devtools/client/debugger/new/images/moz.build
+++ b/devtools/client/debugger/new/images/moz.build
@@ -37,32 +37,33 @@ DevToolsModules(
     'lodash.svg',
     'magnifying-glass.svg',
     'marko.svg',
     'mobx.svg',
     'next-circle.svg',
     'next.svg',
     'nextjs.svg',
     'nuxtjs.svg',
+    'pane-collapse.svg',
+    'pane-expand.svg',
     'pause.svg',
     'plus.svg',
     'preact.svg',
     'prettyPrint.svg',
     'pug.svg',
     'react.svg',
     'redux.svg',
     'regex-match.svg',
     'reload.svg',
     'resume.svg',
     'rxjs.svg',
     'sencha-extjs.svg',
     'stepIn.svg',
     'stepOut.svg',
     'stepOver.svg',
     'tab.svg',
-    'toggle-panes.svg',
     'typescript.svg',
     'underscore.svg',
     'vuejs.svg',
     'webpack.svg',
     'whole-word-match.svg',
     'worker.svg',
 )
new file mode 100644
--- /dev/null
+++ b/devtools/client/debugger/new/images/pane-collapse.svg
@@ -0,0 +1,7 @@
+<!-- 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 16 16" width="16" height="16">
+  <path d="M4 3H2v10h2V3zm7 7V6L8 8l3 2z" fill-opacity=".3"/>
+  <path d="M11.47 10.88A1 1 0 0 0 12 10V6a1 1 0 0 0-1.55-.83l-3 2a1 1 0 0 0 0 1.66l3 2c.3.2.7.23 1.02.05zM8 8l3-2v4L8 8zM2 2h12c.6 0 1 .4 1 1v10c0 .6-.4 1-1 1H2c-.6 0-1-.4-1-1V3c0-.6.4-1 1-1zm12 11V3H5v10h9zM2 13h2V3H2v10z"/>
+</svg>
new file mode 100644
--- /dev/null
+++ b/devtools/client/debugger/new/images/pane-expand.svg
@@ -0,0 +1,7 @@
+<!-- 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 16 16" width="16" height="16">
+  <path d="M4 3H2v10h2V3zM8 6v4l3-2-3-2z" fill-opacity=".3"/>
+  <path d="M7.53 10.88A1 1 0 0 1 7 10V6a1 1 0 0 1 1.55-.83l3 2a1 1 0 0 1 0 1.66l-3 2a1 1 0 0 1-1.02.05zM11 8L8 6v4l3-2zM2 2h12c.6 0 1 .4 1 1v10c0 .6-.4 1-1 1H2c-.6 0-1-.4-1-1V3c0-.6.4-1 1-1zm12 11V3H5v10h9zM2 13h2V3H2v10z"/>
+</svg>
deleted file mode 100644
--- a/devtools/client/debugger/new/images/toggle-panes.svg
+++ /dev/null
@@ -1,7 +0,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/. -->
-<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="#0b0b0b">
-  <path fill-opacity=".3" d="M12,3h2v10h-2V3z M5,9.9V6.1L8,8L5,9.9z"/>
-  <path d="M14,2H2C1.4,2,1,2.4,1,3v10c0,0.6,0.4,1,1,1h12c0.6,0,1-0.4,1-1V3C15,2.4,14.6,2,14,2z M2,13L2,13V3h0h9v10   H2L2,13z M14,13C14,13,14,13,14,13h-2V3h2c0,0,0,0,0,0V13z M8.5,7.2l-3-1.9C4.6,4.7,4,5,4,6.1v3.8c0,1.1,0.6,1.4,1.5,0.8l3-1.9   C9.5,8.3,9.5,7.8,8.5,7.2z M5,9.9V6.1L8,8L5,9.9z"/>
-</svg>
--- a/devtools/client/debugger/new/src/actions/ast/setInScopeLines.js
+++ b/devtools/client/debugger/new/src/actions/ast/setInScopeLines.js
@@ -1,18 +1,23 @@
 /* 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 { getOutOfScopeLocations, getSelectedSource } from "../../selectors";
 import { getSourceLineCount } from "../../utils/source";
 
 import { range, flatMap, uniq, without } from "lodash";
 
-function getOutOfScopeLines(outOfScopeLocations: AstLocation[]) {
+import type { ASTLocation } from "../../types";
+import type { ThunkArgs } from "../types";
+
+function getOutOfScopeLines(outOfScopeLocations: ASTLocation[]) {
   if (!outOfScopeLocations) {
     return null;
   }
 
   return uniq(
     flatMap(outOfScopeLocations, location =>
       range(location.start.line, location.end.line)
     )
--- a/devtools/client/debugger/new/src/actions/navigation.js
+++ b/devtools/client/debugger/new/src/actions/navigation.js
@@ -28,18 +28,18 @@ import type { Action, ThunkArgs } from "
  * @module actions/navigation
  */
 
 /**
  * @memberof actions/navigation
  * @static
  */
 export function willNavigate(event: Object) {
-  return async function({ dispatch, getState, client, sourceMaps }: ThunkArgs) {
-    await sourceMaps.clearSourceMaps();
+  return function({ dispatch, getState, client, sourceMaps }: ThunkArgs) {
+    sourceMaps.clearSourceMaps();
     clearWasmStates();
     clearDocuments();
     clearSymbols();
     clearASTs();
     clearScopes();
     clearSources();
     dispatch(navigate(event.url));
   };
--- a/devtools/client/debugger/new/src/actions/pause/mapFrames.js
+++ b/devtools/client/debugger/new/src/actions/pause/mapFrames.js
@@ -134,16 +134,17 @@ async function expandFrames(
       // Keep outer most frame with true actor ID, and generate uniquie
       // one for the nested frames.
       const id = j == 0 ? frame.id : `${frame.id}-originalFrame${j}`;
       result.push({
         id,
         thread: originalFrame.thread,
         displayName: originalFrame.displayName,
         location: originalFrame.location,
+        source: null,
         scope: frame.scope,
         this: frame.this,
         isOriginal: true,
         // More fields that will be added by the mapDisplayNames and
         // updateFrameLocation.
         generatedLocation: frame.generatedLocation,
         originalDisplayName: originalFrame.displayName
       });
--- a/devtools/client/debugger/new/src/actions/pause/tests/pause.spec.js
+++ b/devtools/client/debugger/new/src/actions/pause/tests/pause.spec.js
@@ -341,27 +341,31 @@ describe("pause", () => {
         {
           displayName: "fooBar",
           generatedLocation: { column: 0, line: 1, sourceId: "foo-wasm" },
           id: mockFrameId,
           isOriginal: true,
           location: originalLocation,
           originalDisplayName: "fooBar",
           scope: { bindings: { arguments: [], variables: {} } },
-          this: undefined
+          source: null,
+          this: undefined,
+          thread: undefined
         },
         {
           displayName: "barZoo",
           generatedLocation: { column: 0, line: 1, sourceId: "foo-wasm" },
           id: `${mockFrameId}-originalFrame1`,
           isOriginal: true,
           location: originalLocation2,
           originalDisplayName: "barZoo",
           scope: { bindings: { arguments: [], variables: {} } },
-          this: undefined
+          source: null,
+          this: undefined,
+          thread: undefined
         }
       ]);
     });
   });
 
   describe("resumed", () => {
     it("should not evaluate expression while stepping", async () => {
       const client = { evaluateExpressions: jest.fn() };
--- a/devtools/client/debugger/new/src/actions/tests/__snapshots__/pending-breakpoints.spec.js.snap
+++ b/devtools/client/debugger/new/src/actions/tests/__snapshots__/pending-breakpoints.spec.js.snap
@@ -16,41 +16,43 @@ Object {
       "column": undefined,
       "line": 5,
       "sourceUrl": "http://localhost:8000/examples/bar.js",
     },
     "hidden": false,
     "location": Object {
       "column": undefined,
       "line": 5,
+      "sourceId": "",
       "sourceUrl": "http://localhost:8000/examples/bar.js",
     },
   },
 }
 `;
 
 exports[`invalid breakpoint location a corrected corresponding pending breakpoint is added 1`] = `
 Object {
   "astLocation": Object {
     "index": 0,
     "name": undefined,
     "offset": Object {
+      "column": 0,
       "line": 7,
       "sourceId": "foo.js",
       "sourceUrl": "http://localhost:8000/examples/foo.js",
     },
   },
   "disabled": false,
   "generatedLocation": Object {
-    "column": undefined,
+    "column": 0,
     "line": 7,
     "sourceUrl": "http://localhost:8000/examples/foo.js",
   },
   "location": Object {
-    "column": undefined,
+    "column": 0,
     "line": 7,
     "sourceUrl": "http://localhost:8000/examples/foo.js",
   },
   "options": Object {
     "condition": null,
     "hidden": false,
     "logValue": null,
   },
--- a/devtools/client/debugger/new/src/actions/tests/helpers/breakpoints.js
+++ b/devtools/client/debugger/new/src/actions/tests/helpers/breakpoints.js
@@ -1,16 +1,19 @@
 /* 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/>. */
 
-export function mockPendingBreakpoint(overrides = {}) {
+// @flow
+
+export function mockPendingBreakpoint(overrides: Object = {}) {
   const { sourceUrl, line, column, condition, disabled, hidden } = overrides;
   return {
     location: {
+      sourceId: "",
       sourceUrl: sourceUrl || "http://localhost:8000/examples/bar.js",
       line: line || 5,
       column: column || undefined
     },
     generatedLocation: {
       sourceUrl: sourceUrl || "http://localhost:8000/examples/bar.js",
       line: line || 5,
       column: column || undefined
@@ -23,29 +26,38 @@ export function mockPendingBreakpoint(ov
       index: 0
     },
     condition: condition || null,
     disabled: disabled || false,
     hidden: hidden || false
   };
 }
 
-export function generateBreakpoint(filename, line = 5, column) {
+export function generateBreakpoint(
+  filename: string,
+  line: number = 5,
+  column: number = 0
+) {
   return {
+    id: "breakpoint",
+    loading: false,
+    originalText: "",
+    text: "",
     location: {
       sourceUrl: `http://localhost:8000/examples/${filename}`,
       sourceId: `${filename}/originalSource`,
       line,
       column
     },
     generatedLocation: {
       sourceUrl: `http://localhost:8000/examples/${filename}`,
       sourceId: filename,
       line,
       column
     },
+    astLocation: undefined,
     options: {
-      condition: null,
+      condition: "",
       hidden: false
     },
     disabled: false
   };
 }
--- a/devtools/client/debugger/new/src/actions/tests/helpers/readFixture.js
+++ b/devtools/client/debugger/new/src/actions/tests/helpers/readFixture.js
@@ -1,14 +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 fs from "fs";
 import path from "path";
 
-export default function readFixture(name) {
+export default function readFixture(name: string) {
   const text = fs.readFileSync(
     path.join(__dirname, `../fixtures/${name}`),
     "utf8"
   );
   return text;
 }
--- a/devtools/client/debugger/new/src/actions/tests/helpers/threadClient.js
+++ b/devtools/client/debugger/new/src/actions/tests/helpers/threadClient.js
@@ -1,13 +1,22 @@
 /* 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/>. */
 
-import { makeBreakpointId } from "../../../utils/breakpoint";
+// @flow
+
+import { makeBreakpointActorId } from "../../../utils/breakpoint";
+
+import type {
+  SourceLocation,
+  SourceActor,
+  SourceActorLocation,
+  BreakpointOptions
+} from "../../../types";
 
 function createSource(name) {
   name = name.replace(/\..*$/, "");
   return {
     source: `function ${name}() {\n  return ${name} \n}`,
     contentType: "text/javascript"
   };
 }
@@ -26,67 +35,79 @@ const sources = [
   "foo.js",
   "bar.js",
   "base.js",
   "bazz.js",
   "jquery.js"
 ];
 
 export const simpleMockThreadClient = {
-  getBreakpointByLocation: jest.fn(),
-  setBreakpoint: (location, _condition) =>
+  getBreakpointByLocation: (jest.fn(): any),
+  setBreakpoint: (location: SourceActorLocation, _condition: string) =>
     Promise.resolve({ id: "hi", actualLocation: location }),
 
-  removeBreakpoint: _id => Promise.resolve(),
+  removeBreakpoint: (_id: string) => Promise.resolve(),
 
-  setBreakpointOptions: (_id, _location, _options, _noSliding) =>
-    Promise.resolve({ sourceId: "a", line: 5 }),
+  setBreakpointOptions: (
+    _id: string,
+    _location: SourceActorLocation,
+    _options: BreakpointOptions,
+    _noSliding: boolean
+  ) => Promise.resolve({ sourceId: "a", line: 5 }),
   setPausePoints: () => Promise.resolve({}),
-  sourceContents: ({ source }) =>
+  sourceContents: ({
+    source
+  }: SourceActor): Promise<{| source: any, contentType: ?string |}> =>
     new Promise((resolve, reject) => {
       if (sources.includes(source)) {
         resolve(createSource(source));
       }
 
       reject(`unknown source: ${source}`);
     })
 };
 
 // Breakpoint Sliding
 function generateCorrectingThreadClient(offset = 0) {
   return {
-    getBreakpointByLocation: jest.fn(),
-    setBreakpoint: (location, condition) => {
+    getBreakpointByLocation: (jest.fn(): any),
+    setBreakpoint: (location: SourceActorLocation, condition: string) => {
       const actualLocation = { ...location, line: location.line + offset };
 
       return Promise.resolve({
-        id: makeBreakpointId(location),
+        id: makeBreakpointActorId(location),
         actualLocation,
         condition
       });
     },
-    sourceContents: ({ source }) => Promise.resolve(createSource(source))
+    sourceContents: ({ source }: SourceActor) =>
+      Promise.resolve(createSource(source))
   };
 }
 
 /* in some cases, a breakpoint may be added, but the source will respond
  * with a different breakpoint location. This is due to the breakpoint being
  * added between functions, or somewhere that doesnt make sense. This function
  * simulates that behavior.
  * */
-export function simulateCorrectThreadClient(offset, location) {
+export function simulateCorrectThreadClient(
+  offset: number,
+  location: SourceLocation
+) {
   const correctedThreadClient = generateCorrectingThreadClient(offset);
   const offsetLine = { line: location.line + offset };
   const correctedLocation = { ...location, ...offsetLine };
   return { correctedThreadClient, correctedLocation };
 }
 
 // sources and tabs
 export const sourceThreadClient = {
-  sourceContents: function({ source }) {
+  sourceContents: function({
+    source
+  }: SourceActor): Promise<{| source: any, contentType: ?string |}> {
     return new Promise((resolve, reject) => {
       if (sources.includes(source)) {
         resolve(createSource(source));
       }
 
       reject(`unknown source: ${source}`);
     });
   },
--- a/devtools/client/debugger/new/src/actions/utils/middleware/log.js
+++ b/devtools/client/debugger/new/src/actions/utils/middleware/log.js
@@ -1,29 +1,32 @@
 /* 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/>. */
 /* global window */
 
+// @flow
+
 import { isTesting } from "devtools-environment";
+import type { ThunkArgs } from "../../types";
 
 const blacklist = [
   "SET_POPUP_OBJECT_PROPERTIES",
   "SET_PAUSE_POINTS",
   "SET_SYMBOLS",
   "OUT_OF_SCOPE_LOCATIONS",
   "MAP_SCOPES",
   "MAP_FRAMES",
   "ADD_SCOPES",
   "IN_SCOPE_LINES",
   "REMOVE_BREAKPOINT",
   "NODE_PROPERTIES_LOADED"
 ];
 
-function cloneAction(action) {
+function cloneAction(action: any) {
   action = action || {};
   action = { ...action };
 
   // ADD_TAB, ...
   if (action.source && action.source.text) {
     const source = { ...action.source, text: "" };
     action.source = source;
   }
@@ -74,28 +77,30 @@ function serializeAction(action) {
     if (action.type === "PAUSED") {
       action = formatPause(action);
     }
 
     // dump(`> ${action.type}...\n ${JSON.stringify(action)}\n`);
     return JSON.stringify(action);
   } catch (e) {
     console.error(e);
+    return "";
   }
 }
 
 /**
  * A middleware that logs all actions coming through the system
  * to the console.
  */
-export function log({ dispatch, getState }) {
-  return next => action => {
+export function log({ dispatch, getState }: ThunkArgs) {
+  return (next: any) => (action: any) => {
     const asyncMsg = !action.status ? "" : `[${action.status}]`;
 
     if (isTesting()) {
+      // $FlowIgnore
       dump(
         `[ACTION] ${action.type} ${asyncMsg} - ${serializeAction(action)}\n`
       );
     } else {
       console.log(action, asyncMsg);
     }
 
     next(action);
--- a/devtools/client/debugger/new/src/actions/utils/middleware/timing.js
+++ b/devtools/client/debugger/new/src/actions/utils/middleware/timing.js
@@ -1,30 +1,32 @@
 /* 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
+
 /* global window */
 
 /**
  * Redux middleware that sets performance markers for all actions such that they
  * will appear in performance tooling under the User Timing API
  */
 
 const mark =
   window.performance && window.performance.mark
     ? window.performance.mark.bind(window.performance)
-    : () => {};
+    : a => {};
 
 const measure =
   window.performance && window.performance.measure
     ? window.performance.measure.bind(window.performance)
-    : () => {};
+    : (a, b, c) => {};
 
-export function timing(store) {
-  return next => action => {
+export function timing(store: any) {
+  return (next: any) => (action: any) => {
     mark(`${action.type}_start`);
     const result = next(action);
     mark(`${action.type}_end`);
     measure(`${action.type}`, `${action.type}_start`, `${action.type}_end`);
     return result;
   };
 }
--- a/devtools/client/debugger/new/src/client/firefox/create.js
+++ b/devtools/client/debugger/new/src/client/firefox/create.js
@@ -41,16 +41,17 @@ export function createFrame(thread: Thre
 
   return {
     id: frame.actor,
     thread,
     displayName: title,
     location,
     generatedLocation: location,
     this: frame.this,
+    source: null,
     scope: frame.environment
   };
 }
 
 function makeSourceId(source) {
   return source.url ? `sourceURL-${source.url}` : `source-${source.actor}`;
 }
 
--- a/devtools/client/debugger/new/src/components/App.css
+++ b/devtools/client/debugger/new/src/components/App.css
@@ -4,42 +4,45 @@
 
 * {
   box-sizing: border-box;
 }
 
 button {
   background: transparent;
   border: none;
+  font-family: inherit;
+  font-size: inherit;
 }
 
 button:hover,
 button:focus {
   background-color: var(--theme-toolbar-background-hover);
 }
 
+.theme-dark button:hover,
+.theme-dark button:focus {
+  background-color: var(--theme-toolbar-hover);
+}
+
 .debugger {
   display: flex;
   flex: 1;
   height: 100%;
 }
 
 .editor-pane {
   display: flex;
   position: relative;
   flex: 1;
-  background-color: var(--theme-tab-toolbar-background);
-  height: calc(100% - 1px);
+  background-color: var(--theme-body-background);
+  height: 100%;
   overflow: hidden;
 }
 
-.theme-dark .editor-pane {
-  background-color: var(--theme-toolbar-background);
-}
-
 .editor-container {
   width: 100%;
 }
 
 .search-container {
   position: absolute;
   top: 0;
   left: 0;
--- a/devtools/client/debugger/new/src/components/Editor/ColumnBreakpoints.css
+++ b/devtools/client/debugger/new/src/components/Editor/ColumnBreakpoints.css
@@ -1,16 +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/>. */
 
 .column-breakpoint {
   display: inline;
   padding: 0;
-  margin-inline-end: 4px;
+  padding-inline-end: 4px;
 }
 
 .column-breakpoint:hover {
   background-color: transparent;
 }
 
 .column-breakpoint svg {
   display: inline;
--- a/devtools/client/debugger/new/src/components/Editor/ColumnBreakpoints.js
+++ b/devtools/client/debugger/new/src/components/Editor/ColumnBreakpoints.js
@@ -1,34 +1,38 @@
 /* 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 React, { Component } from "react";
 
 import ColumnBreakpoint from "./ColumnBreakpoint";
 import "./ColumnBreakpoints.css";
 
 import { getSelectedSource, visibleColumnBreakpoints } from "../../selectors";
 import { connect } from "../../utils/connect";
 import { makeBreakpointId } from "../../utils/breakpoint";
 import { breakpointItemActions } from "./menus/breakpoints";
 import type { BreakpointItemActions } from "./menus/breakpoints";
 
 import type { Source } from "../../types";
 // eslint-disable-next-line max-len
 import type { ColumnBreakpoint as ColumnBreakpointType } from "../../selectors/visibleColumnBreakpoints";
 
-class ColumnBreakpoints extends Component {
-  props: {
-    editor: Object,
-    selectedSource: Source,
-    columnBreakpoints: ColumnBreakpointType[],
-    breakpointActions: BreakpointItemActions
-  };
+type Props = {
+  editor: Object,
+  selectedSource: Source,
+  columnBreakpoints: ColumnBreakpointType[],
+  breakpointActions: BreakpointItemActions
+};
+
+class ColumnBreakpoints extends Component<Props> {
+  props: Props;
 
   render() {
     const {
       editor,
       columnBreakpoints,
       selectedSource,
       breakpointActions
     } = this.props;
--- a/devtools/client/debugger/new/src/components/Editor/ConditionalPanel.css
+++ b/devtools/client/debugger/new/src/components/Editor/ConditionalPanel.css
@@ -28,11 +28,15 @@
   width: calc(100% - 4em);
   border: none;
   background: var(--theme-toolbar-background);
   font-size: 14px;
   color: var(--theme-conditional-breakpoint-color);
   line-height: 30px;
 }
 
+.conditional-breakpoint-panel input:not(:placeholder-shown) {
+  font-family: var(--monospace-font-family);
+}
+
 .conditional-breakpoint-panel input:focus {
   outline-width: 0;
 }
--- a/devtools/client/debugger/new/src/components/Editor/Editor.css
+++ b/devtools/client/debugger/new/src/components/Editor/Editor.css
@@ -1,19 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
 
 .editor-wrapper {
   --debug-line-border: rgb(145, 188, 219);
   --debug-expression-background: rgba(202, 227, 255, 0.5);
-  --editor-searchbar-height: 27px;
   --debug-line-error-border: rgb(255, 0, 0);
   --debug-expression-error-background: rgba(231, 116, 113, 0.3);
-  --editor-header-height: 30px;
   --highlight-line-duration: 1500ms;
 }
 
 .theme-dark .editor-wrapper {
   --debug-expression-background: rgba(202, 227, 255, 0.3);
   --debug-line-border: #7786a2;
 }
 
@@ -43,17 +41,16 @@
  * BUG https://github.com/devtools-html/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;
-  --editor-footer-height: 24px;
 }
 
 html[dir="rtl"] .editor-mount {
   direction: ltr;
 }
 
 .theme-light {
   --gutter-hover-background-color: #dde1e4;
--- a/devtools/client/debugger/new/src/components/Editor/EditorMenu.js
+++ b/devtools/client/debugger/new/src/components/Editor/EditorMenu.js
@@ -1,32 +1,41 @@
 /* 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 { Component } from "react";
 import { connect } from "../../utils/connect";
 import { showMenu } from "devtools-contextmenu";
 
 import { getSourceLocationFromMouseEvent } from "../../utils/editor";
 import { getPrettySource, getIsPaused } from "../../selectors";
 
 import { editorMenuItems, editorItemActions } from "./menus/editor";
-import type { EditorMenuActions } from "./menus/editor";
+
+import type { Source } from "../../types";
+import type { EditorItemActions } from "./menus/editor";
+import type SourceEditor from "../../utils/editor/source-editor";
 
 type Props = {
   contextMenu: ?MouseEvent,
-  editorActions: EditorMenuActions,
-  clearContextMenu: () => {}
+  editorActions: EditorItemActions,
+  clearContextMenu: () => void,
+  editor: SourceEditor,
+  hasPrettySource: boolean,
+  isPaused: boolean,
+  selectedSource: Source
 };
 
-class EditorMenu extends Component {
+class EditorMenu extends Component<Props> {
   props: Props;
 
-  componentWillUpdate(nextProps) {
+  componentWillUpdate(nextProps: Props) {
     this.props.clearContextMenu();
     if (nextProps.contextMenu) {
       this.showMenu(nextProps);
     }
   }
 
   showMenu(props) {
     const {
@@ -36,17 +45,18 @@ class EditorMenu extends Component {
       hasPrettySource,
       isPaused,
       contextMenu: event
     } = props;
 
     const location = getSourceLocationFromMouseEvent(
       editor,
       selectedSource,
-      event
+      // Use a coercion, as contextMenu is optional
+      (event: any)
     );
 
     showMenu(
       event,
       editorMenuItems({
         editorActions,
         selectedSource,
         hasPrettySource,
--- a/devtools/client/debugger/new/src/components/Editor/EmptyLines.js
+++ b/devtools/client/debugger/new/src/components/Editor/EmptyLines.js
@@ -1,26 +1,28 @@
 /* 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 { connect } from "../../utils/connect";
 import { Component } from "react";
 import { getSelectedSource, getEmptyLines } from "../../selectors";
 import type { Source } from "../../types";
 import { toEditorLine } from "../../utils/editor";
 
-type props = {
+type Props = {
   selectedSource: Source,
   editor: Object,
   emptyLines: Object
 };
 
-class EmptyLines extends Component {
-  props: props;
+class EmptyLines extends Component<Props> {
+  props: Props;
 
   disableEmptyLines: Function;
 
   componentDidMount() {
     this.disableEmptyLines();
   }
 
   componentDidUpdate() {
@@ -58,16 +60,19 @@ class EmptyLines extends Component {
 
   render() {
     return null;
   }
 }
 
 const mapStateToProps = state => {
   const selectedSource = getSelectedSource(state);
+  if (!selectedSource) {
+    throw new Error("no selectedSource");
+  }
   const foundEmptyLines = getEmptyLines(state, selectedSource.id);
 
   return {
     selectedSource,
     emptyLines: selectedSource ? foundEmptyLines : []
   };
 };
 
--- a/devtools/client/debugger/new/src/components/Editor/Footer.css
+++ b/devtools/client/debugger/new/src/components/Editor/Footer.css
@@ -31,17 +31,17 @@
 
 .source-footer > .commands > .action {
   display: flex;
   justify-content: center;
   align-items: center;
   transition: opacity 200ms;
   border: none;
   background: transparent;
-  padding: 6px;
+  padding: 4px 6px;
 }
 
 .source-footer > .commands > .action .img {
   height: 100%;
   display: flex;
   flex-direction: column;
   justify-content: center;
 }
--- a/devtools/client/debugger/new/src/components/Editor/Footer.js
+++ b/devtools/client/debugger/new/src/components/Editor/Footer.js
@@ -151,19 +151,19 @@ class SourceFooter extends PureComponent
     if (this.props.horizontal) {
       return;
     }
 
     return (
       <PaneToggleButton
         position="end"
         key="toggle"
-        collapsed={!this.props.endPanelCollapsed}
+        collapsed={this.props.endPanelCollapsed}
         horizontal={this.props.horizontal}
-        handleClick={this.props.togglePaneCollapse}
+        handleClick={(this.props.togglePaneCollapse: any)}
       />
     );
   }
 
   renderCommands() {
     const commands = [
       this.prettyPrintButton(),
       this.blackBoxButton(),
--- a/devtools/client/debugger/new/src/components/Editor/SearchBar.css
+++ b/devtools/client/debugger/new/src/components/Editor/SearchBar.css
@@ -1,22 +1,22 @@
 /* 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/>. */
 
 .search-bar {
   display: flex;
   border: 1px solid transparent;
-  border-top: 1px solid var(--theme-splitter-color);
+  border-top-color: var(--theme-splitter-color);
   height: var(--editor-searchbar-height);
+  transition: border-color 200ms var(--animation-curve);
 }
 
 .search-bar.search-bar-focused {
-  border: 1px solid var(--blue-50);
-  transition: border-color 0.2s ease-in-out;
+  border-color: var(--blue-50);
 }
 
 .search-bar .search-field {
   padding-left: 7px;
 }
 
 .search-bar .search-shadow {
   flex-grow: 1;
--- a/devtools/client/debugger/new/src/components/Editor/Tabs.css
+++ b/devtools/client/debugger/new/src/components/Editor/Tabs.css
@@ -1,140 +1,95 @@
 /* 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/>. */
 
 .source-header {
-  border-bottom: 1px solid var(--theme-splitter-color);
+  display: flex;
   width: 100%;
-  height: 29px;
-  display: flex;
+  height: var(--editor-header-height);
+  border-bottom: 1px solid var(--theme-splitter-color);
+  background-color: var(--theme-toolbar-background);
 }
 
 .source-header * {
   -moz-user-select: none;
   user-select: none;
 }
 
-.source-header .new-tab-btn {
-  padding: 4px;
-  margin-top: 4px;
-  margin-left: 2px;
-  fill: var(--theme-comment);
-  transition: 0.1s ease;
-  align-self: center;
-}
-
-.source-header .new-tab-btn:hover {
-  background-color: var(--theme-toolbar-background-hover);
-}
-
-.source-header .new-tab-btn svg {
-  width: 12px;
-  display: block;
-}
-
 .source-tabs {
   max-width: calc(100% - 80px);
   align-self: flex-start;
 }
 
 .source-tab {
   display: inline-flex;
   align-items: center;
   position: relative;
   min-width: 40px;
   max-width: 100%;
   overflow: hidden;
   padding: 5px;
   cursor: default;
-  height: 30px;
+  height: calc(var(--editor-header-height) - 1px);
   font-size: 12px;
   background-color: transparent;
+  vertical-align: bottom;
 }
 
 .source-tab::before {
   content: "";
   position: absolute;
   top: 0;
   left: 0;
   width: 100%;
   height: 2px;
-  background: transparent;
+  background-color: var(--tab-line-color, transparent);
   transition: transform 250ms var(--animation-curve), opacity 250ms var(--animation-curve);
   opacity: 0;
   transform: scaleX(0);
 }
 
-.source-tab:first-child {
-  margin-inline-start: 0;
-}
-
-.source-tab:not(.active):hover {
-  background: linear-gradient(var(--theme-toolbar-hover) 28px, transparent 1px);
-}
-
-.source-tab:not(.active):hover::before {
-  background: var(--tab-line-hover-color);
-  opacity: 1;
-  transform: scaleX(1);
-}
-
 .source-tab.active {
+  --tab-line-color: var(--tab-line-selected-color);
   color: var(--theme-toolbar-selected-color);
   border-bottom-color: transparent;
 }
 
-.source-tab.active::before {
-  background: var(--tab-line-selected-color);
-  opacity: 1;
-  transform: scaleX(1);
+.source-tab:not(.active):hover {
+  --tab-line-color: var(--tab-line-hover-color);
+  background-color: var(--theme-toolbar-hover);
 }
 
-.theme-dark .source-tab.active {
-  color: var(--theme-toolbar-selected-color);
-}
-
-.source-tab.active path,
-.source-tab:hover path {
-  fill: var(--theme-body-color);
+.source-tab:hover::before,
+.source-tab.active::before {
+  opacity: 1;
+  transform: scaleX(1);
 }
 
 .source-tab .source-icon {
   margin-inline-end: 0;
 }
 
 .source-tab .img.prettyPrint,
 .source-tab .source-icon.blackBox {
   height: 12px;
   width: 12px;
   align-self: center;
 }
 
-.source-tab .prettyPrint path {
-  fill: var(--theme-textbox-box-shadow);
-}
-
 .source-tab .img.react {
   mask: url(/images/react.svg) no-repeat;
   mask-size: 100%;
   height: 14px;
   width: 14px;
   background: var(--theme-highlight-bluegrey);
   top: 0;
 }
 
-.source-tab .blackBox path {
-  fill: var(--theme-textbox-box-shadow);
-}
-
-.theme-dark .source-tab .blackBox circle {
-  fill: var(--theme-body-color);
-}
-
 .source-tab .filename {
   white-space: nowrap;
   text-overflow: ellipsis;
   overflow: hidden;
   padding: 0 4px;
   align-self: center;
   margin-bottom: 1px;
 }
--- a/devtools/client/debugger/new/src/components/Editor/Tabs.js
+++ b/devtools/client/debugger/new/src/components/Editor/Tabs.js
@@ -169,33 +169,33 @@ class Tabs extends PureComponent<Props, 
 
     return <Dropdown panel={Panel} icon={icon} />;
   }
 
   renderStartPanelToggleButton() {
     return (
       <PaneToggleButton
         position="start"
-        collapsed={!this.props.startPanelCollapsed}
-        handleClick={this.props.togglePaneCollapse}
+        collapsed={this.props.startPanelCollapsed}
+        handleClick={(this.props.togglePaneCollapse: any)}
       />
     );
   }
 
   renderEndPanelToggleButton() {
     const { horizontal, endPanelCollapsed, togglePaneCollapse } = this.props;
     if (!horizontal) {
       return;
     }
 
     return (
       <PaneToggleButton
         position="end"
-        collapsed={!endPanelCollapsed}
-        handleClick={togglePaneCollapse}
+        collapsed={endPanelCollapsed}
+        handleClick={(togglePaneCollapse: any)}
         horizontal={horizontal}
       />
     );
   }
 
   render() {
     return (
       <div className="source-header">
--- a/devtools/client/debugger/new/src/components/Editor/index.js
+++ b/devtools/client/debugger/new/src/components/Editor/index.js
@@ -119,17 +119,17 @@ type State = {
 
 class Editor extends PureComponent<Props, State> {
   $editorWrapper: ?HTMLDivElement;
   constructor(props: Props) {
     super(props);
 
     this.state = {
       highlightedLineRange: null,
-      editor: null,
+      editor: (null: any),
       contextMenu: null
     };
   }
 
   componentWillReceiveProps(nextProps) {
     if (!this.state.editor) {
       return;
     }
@@ -237,17 +237,17 @@ class Editor extends PureComponent<Props
       this.props.closeTab(selectedSource);
     }
   };
 
   componentWillUnmount() {
     if (this.state.editor) {
       this.state.editor.destroy();
       this.state.editor.codeMirror.off("scroll", this.onEditorScroll);
-      this.setState({ editor: null });
+      this.setState({ editor: (null: any) });
     }
 
     const searchAgainKey = L10N.getStr("sourceSearch.search.again.key2");
     const searchAgainPrevKey = L10N.getStr(
       "sourceSearch.search.againPrev.key2"
     );
     const shortcuts = this.context.shortcuts;
     shortcuts.off(L10N.getStr("sourceTabs.closeTab.key"));
@@ -601,17 +601,17 @@ class Editor extends PureComponent<Props
     }
 
     return (
       <div>
         <DebugLine editor={editor} />
         <HighlightLine />
         <EmptyLines editor={editor} />
         <Breakpoints editor={editor} />
-        <Preview editor={editor} editorRef={this.$editorWrapper} />;
+        <Preview editor={editor} editorRef={this.$editorWrapper} />
         <Footer editor={editor} horizontal={horizontal} />
         <HighlightLines editor={editor} />
         {
           <EditorMenu
             editor={editor}
             contextMenu={contextMenu}
             clearContextMenu={this.clearContextMenu}
             selectedSource={selectedSource}
--- a/devtools/client/debugger/new/src/components/Editor/menus/source.js
+++ b/devtools/client/debugger/new/src/components/Editor/menus/source.js
@@ -1,3 +1,5 @@
 /* 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
--- a/devtools/client/debugger/new/src/components/Editor/tests/Footer.spec.js
+++ b/devtools/client/debugger/new/src/components/Editor/tests/Footer.spec.js
@@ -23,16 +23,17 @@ function generateDefaults(overrides) {
   return {
     editor: {
       codeMirror: {
         doc: {},
         cursorActivity: jest.fn(),
         on: jest.fn()
       }
     },
+    endPanelCollapsed: false,
     selectedSource: makeSource("foo").source,
     ...overrides
   };
 }
 
 function render(overrides = {}, position = { line: 0, column: 0 }) {
   const clear = jest.fn();
   const props = generateDefaults(overrides);
--- a/devtools/client/debugger/new/src/components/Editor/tests/__snapshots__/Footer.spec.js.snap
+++ b/devtools/client/debugger/new/src/components/Editor/tests/__snapshots__/Footer.spec.js.snap
@@ -6,17 +6,17 @@ exports[`SourceFooter Component default 
 >
   <span
     className="cursor-position"
     title="(Line 2, column 2)"
   >
     (2, 2)
   </span>
   <PaneToggleButton
-    collapsed={true}
+    collapsed={false}
     horizontal={false}
     key="toggle"
     position="end"
   />
 </div>
 `;
 
 exports[`SourceFooter Component move cursor should render new cursor position 1`] = `
@@ -25,15 +25,15 @@ exports[`SourceFooter Component move cur
 >
   <span
     className="cursor-position"
     title="(Line 6, column 11)"
   >
     (6, 11)
   </span>
   <PaneToggleButton
-    collapsed={true}
+    collapsed={false}
     horizontal={false}
     key="toggle"
     position="end"
   />
 </div>
 `;
--- a/devtools/client/debugger/new/src/components/PrimaryPanes/Outline.css
+++ b/devtools/client/debugger/new/src/components/PrimaryPanes/Outline.css
@@ -25,17 +25,16 @@
   margin: 0;
   padding: 0 0 4px 0;
   position: absolute;
   top: 38px;
   bottom: 25px;
   left: 0;
   right: 0;
   list-style-type: none;
-  font-family: var(--monospace-font-family);
   overflow: auto;
 }
 
 .outline-list__class-list {
   margin: 0;
   padding: 0;
   list-style: none;
 }
--- a/devtools/client/debugger/new/src/components/PrimaryPanes/Outline.js
+++ b/devtools/client/debugger/new/src/components/PrimaryPanes/Outline.js
@@ -202,17 +202,17 @@ export class Outline extends Component<P
 
     if (this.props.alphabetizeOutline) {
       namedFunctions = sortBy(namedFunctions, "name");
       classes = sortBy(classes, "klass");
       classFunctions = sortBy(classFunctions, "name");
     }
 
     return (
-      <ul className="outline-list">
+      <ul className="outline-list devtools-monospace">
         {namedFunctions.map(func => this.renderFunction(func))}
         {classes.map(klass => this.renderClassFunctions(klass, classFunctions))}
       </ul>
     );
   }
 
   renderFooter() {
     return (
--- a/devtools/client/debugger/new/src/components/PrimaryPanes/Sources.css
+++ b/devtools/client/debugger/new/src/components/PrimaryPanes/Sources.css
@@ -144,68 +144,68 @@
 .tree-indent {
   border-inline-start: 0 none;
 }
 
 .source-outline-tabs {
   font-size: 12px;
   width: 100%;
   background: var(--theme-body-background);
-  border-top: 1px solid var(--theme-splitter-color);
   display: flex;
   -moz-user-select: none;
   user-select: none;
   box-sizing: border-box;
-  height: 29px;
+  height: var(--editor-header-height);
   margin: 0;
   padding: 0;
+  border-bottom: 1px solid var(--theme-splitter-color);
 }
 
 .source-outline-tabs .tab {
+  align-items: center;
   background-color: var(--theme-toolbar-background);
-  border-top: 2px solid transparent;
-  border-bottom: 1px solid var(--theme-splitter-color);
   color: var(--theme-toolbar-color);
   cursor: default;
   display: inline-flex;
   flex: 1;
   justify-content: center;
-  margin-bottom: 0px;
-  margin-top: -1px;
   overflow: hidden;
-  padding: 5px 8px 7px 8px;
+  padding: 5px;
   position: relative;
   transition: all 0.25s ease;
 }
 
-.source-outline-tabs .tab:not(.active):hover {
-  background-color: var(--theme-toolbar-hover);
-  border-top: 2px solid rgba(0, 0, 0, 0.2);
-}
-
-.theme-dark .source-outline-tabs .tab:hover {
-  border-top: 2px solid var(--tab-line-hover-color);
+.source-outline-tabs .tab::before {
+  content: "";
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 2px;
+  background-color: var(--tab-line-color, transparent);
+  transition: transform 250ms var(--animation-curve), opacity 250ms var(--animation-curve);
+  opacity: 0;
+  transform: scaleX(0);
 }
 
 .source-outline-tabs .tab.active {
-  border-top: 2px solid var(--tab-line-selected-color);
+  --tab-line-color: var(--tab-line-selected-color);
   color: var(--theme-toolbar-selected-color);
-}
-
-.theme-dark .source-outline-tabs .tab.active {
-  color: var(--theme-toolbar-selected-color);
+  border-bottom-color: transparent;
 }
 
-.theme-dark .source-outline-tabs .tab.active:hover {
-  border-top: 2px solid var(--tab-line-selected-color);
+.source-outline-tabs .tab:not(.active):hover {
+  --tab-line-color: var(--tab-line-hover-color);
+  background-color: var(--theme-toolbar-hover);
 }
 
-.source-outline-tabs .tab.active path,
-.source-outline-tabs .tab:hover path {
-  fill: var(--theme-body-color);
+.source-outline-tabs .tab:hover::before,
+.source-outline-tabs .tab.active::before {
+  opacity: 1;
+  transform: scaleX(1);
 }
 
 .source-outline-panel {
   flex: 1;
   overflow: auto;
 }
 
 .source-outline-panel.has-root > div {
--- a/devtools/client/debugger/new/src/components/ProjectSearch.js
+++ b/devtools/client/debugger/new/src/components/ProjectSearch.js
@@ -49,17 +49,18 @@ type Result = {
   matches: Array<Match>,
   sourceId: string
 };
 
 type Item = Result | Match;
 
 type State = {
   inputValue: string,
-  inputFocused: boolean
+  inputFocused: boolean,
+  focusedItem: ?Item
 };
 
 type Props = {
   query: string,
   results: List<Result>,
   status: StatusType,
   activeSearch: ActiveSearchType,
   closeProjectSearch: typeof actions.closeProjectSearch,
@@ -76,33 +77,23 @@ function getFilePath(item: Item, index?:
     : `${item.sourceId}-${item.line}-${item.column}-${index || "$"}`;
 }
 
 function sanitizeQuery(query: string): string {
   // no '\' at end of query
   return query.replace(/\\$/, "");
 }
 
-type FileItem = {
-  setExpanded: (Result, boolean) => mixed,
-  file: Result,
-  expanded: boolean
-};
-type MatchItem = {
-  expanded: null,
-  match: Match
-};
-
 export class ProjectSearch extends Component<Props, State> {
-  focusedItem: ?(FileItem | MatchItem);
   constructor(props: Props) {
     super(props);
     this.state = {
       inputValue: this.props.query || "",
-      inputFocused: false
+      inputFocused: false,
+      focusedItem: null
     };
   }
 
   componentDidMount() {
     const { shortcuts } = this.context;
 
     shortcuts.on(
       L10N.getStr("projectTextSearch.key"),
@@ -168,60 +159,56 @@ export class ProjectSearch extends Compo
       return;
     }
 
     e.stopPropagation();
 
     if (e.key !== "Enter") {
       return;
     }
-    this.focusedItem = null;
+    this.setState({ focusedItem: null });
     const query = sanitizeQuery(this.state.inputValue);
     if (query) {
       this.doSearch(query);
     }
   };
 
   onHistoryScroll = (query: string) => {
     this.setState({ inputValue: query });
   };
 
   onEnterPress = () => {
-    if (!this.focusedItem || this.state.inputFocused) {
+    if (
+      !this.isProjectSearchEnabled() ||
+      !this.state.focusedItem ||
+      this.state.inputFocused
+    ) {
       return;
     }
-    if (this.focusedItem.expanded !== null) {
-      // expanded is not null implies this is a `FileItem`
-      const { setExpanded, file, expanded } = this.focusedItem;
-      setExpanded(file, !expanded);
-    } else {
-      const { match } = this.focusedItem;
-      this.selectMatchItem(match);
+    if (this.state.focusedItem.type === "MATCH") {
+      this.selectMatchItem(this.state.focusedItem);
+    }
+  };
+
+  onFocus = (item: Item) => {
+    if (this.state.focusedItem !== item) {
+      this.setState({ focusedItem: item });
     }
   };
 
   inputOnChange = (e: SyntheticInputEvent<HTMLInputElement>) => {
     const inputValue = e.target.value;
     const { clearSearch } = this.props;
     this.setState({ inputValue });
     if (inputValue === "") {
       clearSearch();
     }
   };
 
-  renderFile = (
-    file: Result,
-    focused: boolean,
-    expanded: boolean,
-    setExpanded: Function
-  ) => {
-    if (focused) {
-      this.focusedItem = { setExpanded, file, expanded };
-    }
-
+  renderFile = (file: Result, focused: boolean, expanded: boolean) => {
     const matchesLength = file.matches.length;
     const matches = ` (${matchesLength} match${matchesLength > 1 ? "es" : ""})`;
 
     return (
       <div
         className={classnames("file-result", { focused })}
         key={file.sourceId}
       >
@@ -229,19 +216,16 @@ export class ProjectSearch extends Compo
         <AccessibleImage className="file" />
         <span className="file-path">{getRelativePath(file.filepath)}</span>
         <span className="matches-summary">{matches}</span>
       </div>
     );
   };
 
   renderMatch = (match: Match, focused: boolean) => {
-    if (focused) {
-      this.focusedItem = { match, expanded: null };
-    }
     return (
       <div
         className={classnames("result", { focused })}
         onClick={() => setTimeout(() => this.selectMatchItem(match), 50)}
       >
         <span className="line-number" key={match.line}>
           {match.line}
         </span>
@@ -250,21 +234,20 @@ export class ProjectSearch extends Compo
     );
   };
 
   renderItem = (
     item: Item,
     depth: number,
     focused: boolean,
     _: any,
-    expanded: boolean,
-    { setExpanded }: { setExpanded: Function }
+    expanded: boolean
   ) => {
     if (item.type === "RESULT") {
-      return this.renderFile(item, focused, expanded, setExpanded);
+      return this.renderFile(item, focused, expanded);
     }
     return this.renderMatch(item, focused);
   };
 
   renderResults = () => {
     const { status, results } = this.props;
     if (!this.props.query) {
       return;
@@ -276,16 +259,18 @@ export class ProjectSearch extends Compo
           getChildren={file => file.matches || []}
           itemHeight={24}
           autoExpandAll={true}
           autoExpandDepth={1}
           autoExpandNodeChildrenLimit={100}
           getParent={item => null}
           getPath={getFilePath}
           renderItem={this.renderItem}
+          focused={this.state.focusedItem}
+          onFocus={this.onFocus}
         />
       );
     }
     const msg =
       status === statusType.fetching
         ? L10N.getStr("loadingText")
         : L10N.getStr("projectTextSearch.noResults");
     return <div className="no-result-msg absolute-center">{msg}</div>;
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/Breakpoint.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/Breakpoint.js
@@ -165,24 +165,26 @@ class Breakpoint extends PureComponent<P
           type="checkbox"
           className="breakpoint-checkbox"
           checked={!breakpoint.disabled}
           onChange={this.handleBreakpointCheckbox}
           onClick={ev => ev.stopPropagation()}
         />
         <label
           htmlFor={breakpoint.id}
-          className="breakpoint-label cm-s-mozilla"
+          className="breakpoint-label cm-s-mozilla devtools-monospace"
           onClick={this.selectBreakpoint}
           title={text}
         >
           <span dangerouslySetInnerHTML={this.highlightText(text, editor)} />
         </label>
         <div className="breakpoint-line-close">
-          <div className="breakpoint-line">{this.getBreakpointLocation()}</div>
+          <div className="breakpoint-line devtools-monospace">
+            {this.getBreakpointLocation()}
+          </div>
           <CloseButton
             handleClick={e => this.removeBreakpoint(e)}
             tooltip={L10N.getStr("breakpoints.removeBreakpointTooltip")}
           />
         </div>
       </div>
     );
   }
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/Breakpoints.css
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/Breakpoints.css
@@ -135,21 +135,16 @@ html .breakpoints-list .breakpoint.pause
   color: var(--theme-comment);
   transition: color 0.15s linear;
 }
 
 .breakpoints-list .breakpoint:hover {
   background-color: var(--search-overlays-semitransparent);
 }
 
-.breakpoints-list .breakpoint .breakpoint-line,
-.breakpoints-list .breakpoint-label {
-  font-family: var(--monospace-font-family);
-}
-
 .breakpoints-list .breakpoint .breakpoint-line {
   font-size: 11px;
   color: var(--theme-comment);
   min-width: 16px;
   text-align: right;
 }
 
 html[dir="rtl"] .breakpoints-list .breakpoint .breakpoint-line {
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/tests/__snapshots__/Breakpoint.spec.js.snap
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/tests/__snapshots__/Breakpoint.spec.js.snap
@@ -10,32 +10,32 @@ exports[`Breakpoint disabled 1`] = `
   <input
     checked={false}
     className="breakpoint-checkbox"
     onChange={[Function]}
     onClick={[Function]}
     type="checkbox"
   />
   <label
-    className="breakpoint-label cm-s-mozilla"
+    className="breakpoint-label cm-s-mozilla devtools-monospace"
     onClick={[Function]}
   >
     <span
       dangerouslySetInnerHTML={
         Object {
           "__html": "",
         }
       }
     />
   </label>
   <div
     className="breakpoint-line-close"
   >
     <div
-      className="breakpoint-line"
+      className="breakpoint-line devtools-monospace"
     >
       53
     </div>
     <CloseButton
       handleClick={[Function]}
       tooltip="Remove breakpoint"
     />
   </div>
@@ -52,32 +52,32 @@ exports[`Breakpoint paused at a differen
   <input
     checked={true}
     className="breakpoint-checkbox"
     onChange={[Function]}
     onClick={[Function]}
     type="checkbox"
   />
   <label
-    className="breakpoint-label cm-s-mozilla"
+    className="breakpoint-label cm-s-mozilla devtools-monospace"
     onClick={[Function]}
   >
     <span
       dangerouslySetInnerHTML={
         Object {
           "__html": "",
         }
       }
     />
   </label>
   <div
     className="breakpoint-line-close"
   >
     <div
-      className="breakpoint-line"
+      className="breakpoint-line devtools-monospace"
     >
       53
     </div>
     <CloseButton
       handleClick={[Function]}
       tooltip="Remove breakpoint"
     />
   </div>
@@ -94,32 +94,32 @@ exports[`Breakpoint paused at a generate
   <input
     checked={true}
     className="breakpoint-checkbox"
     onChange={[Function]}
     onClick={[Function]}
     type="checkbox"
   />
   <label
-    className="breakpoint-label cm-s-mozilla"
+    className="breakpoint-label cm-s-mozilla devtools-monospace"
     onClick={[Function]}
   >
     <span
       dangerouslySetInnerHTML={
         Object {
           "__html": "",
         }
       }
     />
   </label>
   <div
     className="breakpoint-line-close"
   >
     <div
-      className="breakpoint-line"
+      className="breakpoint-line devtools-monospace"
     >
       53
     </div>
     <CloseButton
       handleClick={[Function]}
       tooltip="Remove breakpoint"
     />
   </div>
@@ -136,32 +136,32 @@ exports[`Breakpoint paused at an origina
   <input
     checked={true}
     className="breakpoint-checkbox"
     onChange={[Function]}
     onClick={[Function]}
     type="checkbox"
   />
   <label
-    className="breakpoint-label cm-s-mozilla"
+    className="breakpoint-label cm-s-mozilla devtools-monospace"
     onClick={[Function]}
   >
     <span
       dangerouslySetInnerHTML={
         Object {
           "__html": "",
         }
       }
     />
   </label>
   <div
     className="breakpoint-line-close"
   >
     <div
-      className="breakpoint-line"
+      className="breakpoint-line devtools-monospace"
     >
       5
     </div>
     <CloseButton
       handleClick={[Function]}
       tooltip="Remove breakpoint"
     />
   </div>
@@ -178,32 +178,32 @@ exports[`Breakpoint simple 1`] = `
   <input
     checked={true}
     className="breakpoint-checkbox"
     onChange={[Function]}
     onClick={[Function]}
     type="checkbox"
   />
   <label
-    className="breakpoint-label cm-s-mozilla"
+    className="breakpoint-label cm-s-mozilla devtools-monospace"
     onClick={[Function]}
   >
     <span
       dangerouslySetInnerHTML={
         Object {
           "__html": "",
         }
       }
     />
   </label>
   <div
     className="breakpoint-line-close"
   >
     <div
-      className="breakpoint-line"
+      className="breakpoint-line devtools-monospace"
     >
       53
     </div>
     <CloseButton
       handleClick={[Function]}
       tooltip="Remove breakpoint"
     />
   </div>
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/CommandBar.css
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/CommandBar.css
@@ -111,17 +111,18 @@ html[dir="rtl"] .command-bar {
 .command-bar .active .skipPausing {
   background-color: var(--theme-highlight-blue);
 }
 
 .bottom {
   border-bottom: none;
   background-color: var(--theme-body-background);
   border-top: 1px solid var(--theme-splitter-color);
-  flex: 0 0 25px;
+  flex: none;
+  height: var(--editor-footer-height);
 }
 
 .command-bar.bottom {
   justify-content: flex-end;
 }
 
 .command-bar.bottom > button {
   color: var(--theme-comment);
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Expressions.css
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Expressions.css
@@ -111,11 +111,11 @@
 .expression-content .tree-node {
   overflow-x: hidden;
 }
 
 .expression-content .tree-node[data-expandable="false"][aria-level="1"] {
   padding-inline-start: 10px;
 }
 
-.expression-input {
-  max-width: 50%;
+.input-expression:not(:placeholder-shown) {
+  font-family: var(--monospace-font-family);
 }
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Expressions.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Expressions.js
@@ -66,20 +66,27 @@ class Expressions extends Component<Prop
       editing: false,
       editIndex: -1,
       inputValue: "",
       focused: false
     };
   }
 
   componentDidMount() {
-    const { expressions, evaluateExpressions } = this.props;
+    const { expressions, evaluateExpressions, showInput } = this.props;
+
     if (expressions.size > 0) {
       evaluateExpressions();
     }
+
+    // Ensures that the input is focused when the "+"
+    // is clicked while the panel is collapsed
+    if (showInput && this._input) {
+      this._input.focus();
+    }
   }
 
   clear = () => {
     this.setState(() => {
       this.props.clearExpressionError();
       return { editing: false, editIndex: -1, inputValue: "" };
     });
   };
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/Frame.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/Frame.js
@@ -10,30 +10,29 @@ import classNames from "classnames";
 
 import AccessibleImage from "../../shared/AccessibleImage";
 import { formatDisplayName } from "../../../utils/pause/frames";
 import { getFilename, getFileURL } from "../../../utils/source";
 import FrameMenu from "./FrameMenu";
 import FrameIndent from "./FrameIndent";
 
 import type { Frame } from "../../../types";
-import type { LocalFrame } from "./types";
 
 type FrameTitleProps = {
   frame: Frame,
   options: Object,
   l10n: Object
 };
 
 function FrameTitle({ frame, options = {}, l10n }: FrameTitleProps) {
   const displayName = formatDisplayName(frame, options, l10n);
   return <span className="title">{displayName}</span>;
 }
 
-type FrameLocationProps = { frame: LocalFrame, displayFullUrl: boolean };
+type FrameLocationProps = { frame: Frame, displayFullUrl: boolean };
 
 function FrameLocation({ frame, displayFullUrl = false }: FrameLocationProps) {
   if (!frame.source) {
     return null;
   }
 
   if (frame.library) {
     return (
@@ -57,18 +56,18 @@ function FrameLocation({ frame, displayF
       <span className="line">{location.line}</span>
     </span>
   );
 }
 
 FrameLocation.displayName = "FrameLocation";
 
 type FrameComponentProps = {
-  frame: LocalFrame,
-  selectedFrame: LocalFrame,
+  frame: Frame,
+  selectedFrame: Frame,
   copyStackTrace: Function,
   toggleFrameworkGrouping: Function,
   selectFrame: Function,
   frameworkGroupingOn: boolean,
   hideLocation: boolean,
   shouldMapDisplayName: boolean,
   toggleBlackBox: Function,
   displayFullUrl: boolean,
@@ -134,16 +133,20 @@ export default class FrameComponent exte
       selectable
     } = this.props;
     const { l10n } = this.context;
 
     const className = classNames("frame", {
       selected: selectedFrame && selectedFrame.id === frame.id
     });
 
+    if (!frame.source) {
+      throw new Error("no frame source");
+    }
+
     const title = getFrameTitle
       ? getFrameTitle(
           `${getFileURL(frame.source, false)}:${frame.location.line}`
         )
       : undefined;
 
     return (
       <div
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/FrameIndent.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/FrameIndent.js
@@ -1,12 +1,14 @@
 /* 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 React from "react";
 
 export default function FrameIndent() {
   return (
     <span className="frame-indent clipboard-only">
       &nbsp;&nbsp;&nbsp;&nbsp;
     </span>
   );
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/FrameMenu.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/FrameMenu.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 { showMenu } from "devtools-contextmenu";
 import { copyToTheClipboard } from "../../../utils/clipboard";
-import type { LocalFrame } from "./types";
-import type { ContextMenuItem } from "../../../types";
+import type { ContextMenuItem, Frame } from "../../../types";
 import { kebabCase } from "lodash";
 
 const blackboxString = "sourceFooter.blackbox";
 const unblackboxString = "sourceFooter.unblackbox";
 
 function formatMenuElement(
   labelString: string,
   click: Function,
@@ -52,17 +51,17 @@ function blackBoxSource(source, toggleBl
   const toggleBlackBoxString = source.isBlackBoxed
     ? unblackboxString
     : blackboxString;
 
   return formatMenuElement(toggleBlackBoxString, () => toggleBlackBox(source));
 }
 
 export default function FrameMenu(
-  frame: LocalFrame,
+  frame: Frame,
   frameworkGroupingOn: boolean,
   callbacks: Object,
   event: SyntheticMouseEvent<HTMLElement>
 ) {
   event.stopPropagation();
   event.preventDefault();
 
   const menuOptions = [];
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/Group.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/Group.js
@@ -10,21 +10,21 @@ import classNames from "classnames";
 import { getLibraryFromUrl } from "../../../utils/pause/frames";
 
 import FrameMenu from "./FrameMenu";
 import AccessibleImage from "../../shared/AccessibleImage";
 import FrameComponent from "./Frame";
 
 import "./Group.css";
 
-import type { LocalFrame } from "./types";
+import type { Frame } from "../../../types";
 import Badge from "../../shared/Badge";
 import FrameIndent from "./FrameIndent";
 
-type FrameLocationProps = { frame: LocalFrame, expanded: boolean };
+type FrameLocationProps = { frame: Frame, expanded: boolean };
 function FrameLocation({ frame, expanded }: FrameLocationProps) {
   const library = frame.library || getLibraryFromUrl(frame);
   if (!library) {
     return null;
   }
 
   const arrowClassName = classNames("arrow", { expanded });
   return (
@@ -34,18 +34,18 @@ function FrameLocation({ frame, expanded
       <span className="group-description-name">{library}</span>
     </span>
   );
 }
 
 FrameLocation.displayName = "FrameLocation";
 
 type Props = {
-  group: LocalFrame[],
-  selectedFrame: LocalFrame,
+  group: Frame[],
+  selectedFrame: Frame,
   selectFrame: Function,
   toggleFrameworkGrouping: Function,
   copyStackTrace: Function,
   toggleBlackBox: Function,
   frameworkGroupingOn: boolean,
   displayFullUrl: boolean,
   getFrameTitle?: string => string,
   disableContextMenu: boolean,
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/index.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/index.js
@@ -21,18 +21,16 @@ import { copyToTheClipboard } from "../.
 
 import {
   getFrameworkGroupingState,
   getSelectedFrame,
   getCallStackFrames,
   getPauseReason
 } from "../../../selectors";
 
-import type { LocalFrame } from "./types";
-
 import "./Frames.css";
 
 const NUM_FRAMES_SHOWN = 7;
 
 type Props = {
   frames: Array<Frame>,
   frameworkGroupingOn: boolean,
   selectedFrame: Object,
@@ -108,56 +106,56 @@ class Frames extends Component<Props, St
     copyToTheClipboard(framesToCopy);
   };
 
   toggleFrameworkGrouping = () => {
     const { toggleFrameworkGrouping, frameworkGroupingOn } = this.props;
     toggleFrameworkGrouping(!frameworkGroupingOn);
   };
 
-  renderFrames(frames: LocalFrame[]) {
+  renderFrames(frames: Frame[]) {
     const {
       selectFrame,
       selectedFrame,
       toggleBlackBox,
       frameworkGroupingOn,
       displayFullUrl,
       getFrameTitle,
       disableContextMenu,
       selectable = false
     } = this.props;
 
     const framesOrGroups = this.truncateFrames(this.collapseFrames(frames));
-    type FrameOrGroup = LocalFrame | LocalFrame[];
+    type FrameOrGroup = Frame | Frame[];
 
     // We're not using a <ul> because it adds new lines before and after when
     // the user copies the trace. Needed for the console which has several
     // places where we don't want to have those new lines.
     return (
       <div role="list">
         {framesOrGroups.map(
           (frameOrGroup: FrameOrGroup) =>
             frameOrGroup.id ? (
               <FrameComponent
-                frame={frameOrGroup}
+                frame={(frameOrGroup: any)}
                 toggleFrameworkGrouping={this.toggleFrameworkGrouping}
                 copyStackTrace={this.copyStackTrace}
                 frameworkGroupingOn={frameworkGroupingOn}
                 selectFrame={selectFrame}
                 selectedFrame={selectedFrame}
                 toggleBlackBox={toggleBlackBox}
                 key={String(frameOrGroup.id)}
                 displayFullUrl={displayFullUrl}
                 getFrameTitle={getFrameTitle}
                 disableContextMenu={disableContextMenu}
                 selectable={selectable}
               />
             ) : (
               <Group
-                group={frameOrGroup}
+                group={(frameOrGroup: any)}
                 toggleFrameworkGrouping={this.toggleFrameworkGrouping}
                 copyStackTrace={this.copyStackTrace}
                 frameworkGroupingOn={frameworkGroupingOn}
                 selectFrame={selectFrame}
                 selectedFrame={selectedFrame}
                 toggleBlackBox={toggleBlackBox}
                 key={frameOrGroup[0].id}
                 displayFullUrl={displayFullUrl}
@@ -166,23 +164,23 @@ class Frames extends Component<Props, St
                 selectable={selectable}
               />
             )
         )}
       </div>
     );
   }
 
-  renderToggleButton(frames: LocalFrame[]) {
+  renderToggleButton(frames: Frame[]) {
     const { l10n } = this.context;
     const buttonMessage = this.state.showAllFrames
       ? l10n.getStr("callStack.collapse")
       : l10n.getStr("callStack.expand");
 
-    frames = this.collapseFrames(frames);
+    frames = (this.collapseFrames(frames): any);
     if (frames.length <= NUM_FRAMES_SHOWN) {
       return null;
     }
 
     return (
       <div className="show-more-container">
         <button className="show-more" onClick={this.toggleFramesDisplay}>
           {buttonMessage}
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/tests/Frame.spec.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/tests/Frame.spec.js
@@ -2,132 +2,96 @@
  * 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 React from "react";
 import { shallow, mount } from "enzyme";
 import Frame from "../Frame.js";
+import { makeMockFrame, makeMockSource } from "../../../../utils/test-mockup";
 
 import FrameMenu from "../FrameMenu";
 jest.mock("../FrameMenu", () => jest.fn());
 
-function frameProperties(frame, selectedFrame, overrides = {}) {
+function frameProperties(frame, selectedFrame: any, overrides = {}) {
   return {
     frame,
     selectedFrame,
     copyStackTrace: jest.fn(),
     contextTypes: {},
     selectFrame: jest.fn(),
     toggleBlackBox: jest.fn(),
     displayFullUrl: false,
     frameworkGroupingOn: false,
     selectable: true,
     toggleFrameworkGrouping: null,
     ...overrides
   };
 }
 
 function render(frameToSelect = {}, overrides = {}, propsOverrides = {}) {
-  const defaultFrame = {
-    id: 1,
-    source: {
-      url: "foo-view.js",
-      isBlackBoxed: false
-    },
-    displayName: "renderFoo",
-    frameworkGroupingOn: false,
-    toggleFrameworkGrouping: jest.fn(),
-    library: false,
-    location: {
-      line: 10
-    }
-  };
+  const source = makeMockSource("foo-view.js");
+  const defaultFrame = makeMockFrame("1", source, undefined, 10, "renderFoo");
+
   const frame = { ...defaultFrame, ...overrides };
   const selectedFrame = { ...frame, ...frameToSelect };
 
   const props = frameProperties(frame, selectedFrame, propsOverrides);
   const component = shallow(<Frame {...props} />);
   return { component, props };
 }
 
 describe("Frame", () => {
   it("user frame", () => {
     const { component } = render();
     expect(component).toMatchSnapshot();
   });
 
   it("user frame (not selected)", () => {
-    const { component } = render({ id: 2 });
+    const { component } = render({ id: "2" });
     expect(component).toMatchSnapshot();
   });
 
   it("library frame", () => {
+    const source = makeMockSource("backbone.js");
     const backboneFrame = {
-      id: 3,
-      source: { url: "backbone.js" },
-      displayName: "updateEvents",
-      library: "backbone",
-      location: {
-        line: 12
-      }
+      ...makeMockFrame("3", source, undefined, 12, "updateEvents"),
+      library: "backbone"
     };
 
-    const { component } = render({ id: 3 }, backboneFrame);
+    const { component } = render({ id: "3" }, backboneFrame);
     expect(component).toMatchSnapshot();
   });
 
-  fit("filename only", () => {
-    const frame = {
-      id: 1,
-      source: {
-        url: "https://firefox.com/assets/src/js/foo-view.js"
-      },
-      displayName: "renderFoo",
-      location: {
-        line: 10
-      }
-    };
+  it("filename only", () => {
+    const source = makeMockSource(
+      "https://firefox.com/assets/src/js/foo-view.js"
+    );
+    const frame = makeMockFrame("1", source, undefined, 10, "renderFoo");
 
     const props = frameProperties(frame, null);
     const component = mount(<Frame {...props} />);
     expect(component.text()).toBe("\trenderFoo foo-view.js:10\n");
   });
 
   it("full URL", () => {
     const url = `https://${"a".repeat(100)}.com/assets/src/js/foo-view.js`;
-    const frame = {
-      id: 1,
-      source: {
-        url
-      },
-      displayName: "renderFoo",
-      location: {
-        line: 10
-      }
-    };
+    const source = makeMockSource(url);
+    const frame = makeMockFrame("1", source, undefined, 10, "renderFoo");
 
     const props = frameProperties(frame, null, { displayFullUrl: true });
     const component = mount(<Frame {...props} />);
     expect(component.text()).toBe(`renderFoo ${url}:10`);
   });
 
   it("getFrameTitle", () => {
     const url = `https://${"a".repeat(100)}.com/assets/src/js/foo-view.js`;
-    const frame = {
-      id: 1,
-      source: {
-        url
-      },
-      displayName: "renderFoo",
-      location: {
-        line: 10
-      }
-    };
+    const source = makeMockSource(url);
+    const frame = makeMockFrame("1", source, undefined, 10, "renderFoo");
 
     const props = frameProperties(frame, null, {
       getFrameTitle: x => `Jump to ${x}`
     });
     const component = shallow(<Frame {...props} />);
     expect(component.prop("title")).toBe(`Jump to ${url}:10`);
     expect(component).toMatchSnapshot();
   });
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/tests/FrameMenu.spec.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/tests/FrameMenu.spec.js
@@ -4,41 +4,38 @@
 
 // @flow
 
 import FrameMenu from "../FrameMenu";
 import { kebabCase } from "lodash";
 
 import { showMenu } from "devtools-contextmenu";
 import { copyToTheClipboard } from "../../../../utils/clipboard";
+import { makeMockFrame, makeMockSource } from "../../../../utils/test-mockup";
+
 jest.mock("devtools-contextmenu", () => ({ showMenu: jest.fn() }));
 jest.mock("../../../../utils/clipboard", () => ({
   copyToTheClipboard: jest.fn()
 }));
 
 function generateMockId(labelString) {
   const label = L10N.getStr(labelString);
   return `node-menu-${kebabCase(label)}`;
 }
 
 describe("FrameMenu", () => {
   let mockEvent: any;
   let mockFrame;
-  let emptyFrame;
+  let emptyFrame: any;
   let callbacks;
   let frameworkGroupingOn;
   let toggleFrameworkGrouping;
 
   beforeEach(() => {
-    mockFrame = {
-      source: {
-        url: "isFake",
-        isBlackBoxed: false
-      }
-    };
+    mockFrame = makeMockFrame(undefined, makeMockSource("isFake"));
     mockEvent = {
       stopPropagation: jest.fn(),
       preventDefault: jest.fn()
     };
     callbacks = {
       toggleFrameworkGrouping,
       toggleBlackbox: jest.fn(),
       copyToTheClipboard
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/tests/Frames.spec.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/tests/Frames.spec.js
@@ -4,16 +4,17 @@
 
 // @flow
 
 import React from "react";
 import { mount, shallow } from "enzyme";
 import Frames from "../index.js";
 // eslint-disable-next-line
 import { formatCallStackFrames } from "../../../../selectors/getCallStackFrames";
+import { makeMockFrame, makeMockSource } from "../../../../utils/test-mockup";
 
 function render(overrides = {}) {
   const defaultProps = {
     frames: null,
     selectedFrame: null,
     frameworkGroupingOn: false,
     toggleFrameworkGrouping: jest.fn(),
     contextTypes: {},
@@ -186,33 +187,33 @@ describe("Frames", () => {
       });
 
       expect(component.find("Group").prop("getFrameTitle")).toBe(getFrameTitle);
     });
   });
 
   describe("Blackboxed Frames", () => {
     it("filters blackboxed frames", () => {
+      const source1 = makeMockSource(undefined, "1");
+      const source2 = makeMockSource(undefined, "2");
+      source2.isBlackBoxed = true;
+
       const frames = [
-        { id: 1, location: { sourceId: "1" } },
-        { id: 2, location: { sourceId: "2" } },
-        { id: 3, location: { sourceId: "1" } },
-        { id: 8, location: { sourceId: "2" } }
+        makeMockFrame("1", source1),
+        makeMockFrame("2", source2),
+        makeMockFrame("3", source1),
+        makeMockFrame("8", source2)
       ];
 
       const sources = {
-        "1": { id: "1" },
-        "2": { id: "2", isBlackBoxed: true }
+        "1": source1,
+        "2": source2
       };
 
-      const processedFrames = formatCallStackFrames(
-        frames,
-        sources,
-        sources["1"]
-      );
+      const processedFrames = formatCallStackFrames(frames, sources, source1);
       const selectedFrame = frames[0];
 
       const component = render({
         frames: processedFrames,
         frameworkGroupingOn: false,
         selectedFrame
       });
 
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/tests/Group.spec.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/tests/Group.spec.js
@@ -2,24 +2,26 @@
  * 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 React from "react";
 import { shallow } from "enzyme";
 import Group from "../Group.js";
+import { makeMockFrame, makeMockSource } from "../../../../utils/test-mockup";
 
 import FrameMenu from "../FrameMenu";
 jest.mock("../FrameMenu", () => jest.fn());
 
 function render(overrides = {}) {
+  const frame = { ...makeMockFrame(), displayName: "foo", library: "Back" };
   const defaultProps = {
-    group: [{ displayName: "foo", library: "Back" }],
-    selectedFrame: {},
+    group: [frame],
+    selectedFrame: frame,
     frameworkGroupingOn: true,
     toggleFrameworkGrouping: jest.fn(),
     selectFrame: jest.fn(),
     copyStackTrace: jest.fn(),
     toggleBlackBox: jest.fn(),
     disableContextMenu: false,
     displayFullUrl: false,
     selectable: true
@@ -34,98 +36,60 @@ function render(overrides = {}) {
 
 describe("Group", () => {
   it("displays a group", () => {
     const { component } = render();
     expect(component).toMatchSnapshot();
   });
 
   it("passes the getFrameTitle prop to the Frame components", () => {
+    const mahscripts = makeMockSource("http://myfile.com/mahscripts.js");
+    const back = makeMockSource("http://myfile.com/back.js");
     const group = [
       {
-        id: 1,
-        library: "Back",
-        displayName: "renderFoo",
-        location: {
-          line: 55
-        },
-        source: {
-          url: "http://myfile.com/mahscripts.js"
-        }
+        ...makeMockFrame("1", mahscripts, undefined, 55, "renderFoo"),
+        library: "Back"
       },
       {
-        id: 2,
-        library: "Back",
-        displayName: "a",
-        location: {
-          line: 55
-        },
-        source: {
-          url: "http://myfile.com/back.js"
-        }
+        ...makeMockFrame("2", back, undefined, 55, "a"),
+        library: "Back"
       },
       {
-        id: 3,
-        library: "Back",
-        displayName: "b",
-        location: {
-          line: 55
-        },
-        source: {
-          url: "http://myfile.com/back.js"
-        }
+        ...makeMockFrame("3", back, undefined, 55, "b"),
+        library: "Back"
       }
     ];
     const getFrameTitle = () => {};
     const { component } = render({ group, getFrameTitle });
 
     component.setState({ expanded: true });
 
     const frameComponents = component.find("Frame");
     expect(frameComponents).toHaveLength(3);
     frameComponents.forEach(node => {
       expect(node.prop("getFrameTitle")).toBe(getFrameTitle);
     });
     expect(component).toMatchSnapshot();
   });
 
   it("renders group with anonymous functions", () => {
+    const mahscripts = makeMockSource("http://myfile.com/mahscripts.js");
+    const back = makeMockSource("http://myfile.com/back.js");
     const group = [
       {
-        id: 1,
-        library: "Back",
-        displayName: "",
-        location: {
-          line: 55
-        },
-        source: {
-          url: "http://myfile.com/mahscripts.js"
-        }
+        ...makeMockFrame("1", mahscripts, undefined, 55),
+        library: "Back"
       },
       {
-        id: 2,
-        library: "Back",
-        displayName: "",
-        location: {
-          line: 55
-        },
-        source: {
-          url: "http://myfile.com/back.js"
-        }
+        ...makeMockFrame("2", back, undefined, 55),
+        library: "Back"
       },
       {
-        id: 3,
-        library: "Back",
-        displayName: "",
-        location: {
-          line: 55
-        },
-        source: {
-          url: "http://myfile.com/back.js"
-        }
+        ...makeMockFrame("3", back, undefined, 55),
+        library: "Back"
       }
     ];
 
     const { component } = render({ group });
     expect(component).toMatchSnapshot();
     component.setState({ expanded: true });
     expect(component).toMatchSnapshot();
   });
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/tests/__snapshots__/Frame.spec.js.snap
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/tests/__snapshots__/Frame.spec.js.snap
@@ -11,23 +11,50 @@ exports[`Frame getFrameTitle 1`] = `
   tabIndex={0}
   title="Jump to https://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com/assets/src/js/foo-view.js:10"
 >
   <FrameIndent />
   <FrameTitle
     frame={
       Object {
         "displayName": "renderFoo",
-        "id": 1,
+        "generatedLocation": Object {
+          "line": 10,
+          "sourceId": "source",
+        },
+        "id": "1",
         "location": Object {
           "line": 10,
+          "sourceId": "source",
+        },
+        "scope": Object {
+          "actor": "scope-actor",
+          "bindings": Object {
+            "arguments": Array [],
+            "variables": Object {},
+          },
+          "function": null,
+          "object": null,
+          "parent": null,
+          "type": "block",
         },
         "source": Object {
+          "contentType": "text/javascript",
+          "id": "source",
+          "introductionUrl": null,
+          "isBlackBoxed": false,
+          "isPrettyPrinted": false,
+          "isWasm": false,
+          "loadedState": "unloaded",
+          "relativeUrl": "https://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com/assets/src/js/foo-view.js",
+          "text": "",
           "url": "https://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com/assets/src/js/foo-view.js",
         },
+        "this": Object {},
+        "thread": "FakeThread",
       }
     }
     options={
       Object {
         "shouldMapDisplayName": true,
       }
     }
   />
@@ -36,23 +63,50 @@ exports[`Frame getFrameTitle 1`] = `
   >
      
   </span>
   <FrameLocation
     displayFullUrl={false}
     frame={
       Object {
         "displayName": "renderFoo",
-        "id": 1,
+        "generatedLocation": Object {
+          "line": 10,
+          "sourceId": "source",
+        },
+        "id": "1",
         "location": Object {
           "line": 10,
+          "sourceId": "source",
+        },
+        "scope": Object {
+          "actor": "scope-actor",
+          "bindings": Object {
+            "arguments": Array [],
+            "variables": Object {},
+          },
+          "function": null,
+          "object": null,
+          "parent": null,
+          "type": "block",
         },
         "source": Object {
+          "contentType": "text/javascript",
+          "id": "source",
+          "introductionUrl": null,
+          "isBlackBoxed": false,
+          "isPrettyPrinted": false,
+          "isWasm": false,
+          "loadedState": "unloaded",
+          "relativeUrl": "https://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com/assets/src/js/foo-view.js",
+          "text": "",
           "url": "https://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com/assets/src/js/foo-view.js",
         },
+        "this": Object {},
+        "thread": "FakeThread",
       }
     }
   />
   <br
     className="clipboard-only"
   />
 </div>
 `;
@@ -67,26 +121,51 @@ exports[`Frame library frame 1`] = `
   role="listitem"
   tabIndex={0}
 >
   <FrameIndent />
   <FrameTitle
     frame={
       Object {
         "displayName": "updateEvents",
-        "frameworkGroupingOn": false,
-        "id": 3,
+        "generatedLocation": Object {
+          "line": 12,
+          "sourceId": "source",
+        },
+        "id": "3",
         "library": "backbone",
         "location": Object {
           "line": 12,
+          "sourceId": "source",
+        },
+        "scope": Object {
+          "actor": "scope-actor",
+          "bindings": Object {
+            "arguments": Array [],
+            "variables": Object {},
+          },
+          "function": null,
+          "object": null,
+          "parent": null,
+          "type": "block",
         },
         "source": Object {
+          "contentType": "text/javascript",
+          "id": "source",
+          "introductionUrl": null,
+          "isBlackBoxed": false,
+          "isPrettyPrinted": false,
+          "isWasm": false,
+          "loadedState": "unloaded",
+          "relativeUrl": "backbone.js",
+          "text": "",
           "url": "backbone.js",
         },
-        "toggleFrameworkGrouping": [MockFunction],
+        "this": Object {},
+        "thread": "FakeThread",
       }
     }
     options={
       Object {
         "shouldMapDisplayName": true,
       }
     }
   />
@@ -95,26 +174,51 @@ exports[`Frame library frame 1`] = `
   >
      
   </span>
   <FrameLocation
     displayFullUrl={false}
     frame={
       Object {
         "displayName": "updateEvents",
-        "frameworkGroupingOn": false,
-        "id": 3,
+        "generatedLocation": Object {
+          "line": 12,
+          "sourceId": "source",
+        },
+        "id": "3",
         "library": "backbone",
         "location": Object {
           "line": 12,
+          "sourceId": "source",
+        },
+        "scope": Object {
+          "actor": "scope-actor",
+          "bindings": Object {
+            "arguments": Array [],
+            "variables": Object {},
+          },
+          "function": null,
+          "object": null,
+          "parent": null,
+          "type": "block",
         },
         "source": Object {
+          "contentType": "text/javascript",
+          "id": "source",
+          "introductionUrl": null,
+          "isBlackBoxed": false,
+          "isPrettyPrinted": false,
+          "isWasm": false,
+          "loadedState": "unloaded",
+          "relativeUrl": "backbone.js",
+          "text": "",
           "url": "backbone.js",
         },
-        "toggleFrameworkGrouping": [MockFunction],
+        "this": Object {},
+        "thread": "FakeThread",
       }
     }
   />
   <br
     className="clipboard-only"
   />
 </div>
 `;
@@ -129,27 +233,50 @@ exports[`Frame user frame (not selected)
   role="listitem"
   tabIndex={0}
 >
   <FrameIndent />
   <FrameTitle
     frame={
       Object {
         "displayName": "renderFoo",
-        "frameworkGroupingOn": false,
-        "id": 1,
-        "library": false,
+        "generatedLocation": Object {
+          "line": 10,
+          "sourceId": "source",
+        },
+        "id": "1",
         "location": Object {
           "line": 10,
+          "sourceId": "source",
+        },
+        "scope": Object {
+          "actor": "scope-actor",
+          "bindings": Object {
+            "arguments": Array [],
+            "variables": Object {},
+          },
+          "function": null,
+          "object": null,
+          "parent": null,
+          "type": "block",
         },
         "source": Object {
+          "contentType": "text/javascript",
+          "id": "source",
+          "introductionUrl": null,
           "isBlackBoxed": false,
+          "isPrettyPrinted": false,
+          "isWasm": false,
+          "loadedState": "unloaded",
+          "relativeUrl": "foo-view.js",
+          "text": "",
           "url": "foo-view.js",
         },
-        "toggleFrameworkGrouping": [MockFunction],
+        "this": Object {},
+        "thread": "FakeThread",
       }
     }
     options={
       Object {
         "shouldMapDisplayName": true,
       }
     }
   />
@@ -158,27 +285,50 @@ exports[`Frame user frame (not selected)
   >
      
   </span>
   <FrameLocation
     displayFullUrl={false}
     frame={
       Object {
         "displayName": "renderFoo",
-        "frameworkGroupingOn": false,
-        "id": 1,
-        "library": false,
+        "generatedLocation": Object {
+          "line": 10,
+          "sourceId": "source",
+        },
+        "id": "1",
         "location": Object {
           "line": 10,
+          "sourceId": "source",
+        },
+        "scope": Object {
+          "actor": "scope-actor",
+          "bindings": Object {
+            "arguments": Array [],
+            "variables": Object {},
+          },
+          "function": null,
+          "object": null,
+          "parent": null,
+          "type": "block",
         },
         "source": Object {
+          "contentType": "text/javascript",
+          "id": "source",
+          "introductionUrl": null,
           "isBlackBoxed": false,
+          "isPrettyPrinted": false,
+          "isWasm": false,
+          "loadedState": "unloaded",
+          "relativeUrl": "foo-view.js",
+          "text": "",
           "url": "foo-view.js",
         },
-        "toggleFrameworkGrouping": [MockFunction],
+        "this": Object {},
+        "thread": "FakeThread",
       }
     }
   />
   <br
     className="clipboard-only"
   />
 </div>
 `;
@@ -193,27 +343,50 @@ exports[`Frame user frame 1`] = `
   role="listitem"
   tabIndex={0}
 >
   <FrameIndent />
   <FrameTitle
     frame={
       Object {
         "displayName": "renderFoo",
-        "frameworkGroupingOn": false,
-        "id": 1,
-        "library": false,
+        "generatedLocation": Object {
+          "line": 10,
+          "sourceId": "source",
+        },
+        "id": "1",
         "location": Object {
           "line": 10,
+          "sourceId": "source",
+        },
+        "scope": Object {
+          "actor": "scope-actor",
+          "bindings": Object {
+            "arguments": Array [],
+            "variables": Object {},
+          },
+          "function": null,
+          "object": null,
+          "parent": null,
+          "type": "block",
         },
         "source": Object {
+          "contentType": "text/javascript",
+          "id": "source",
+          "introductionUrl": null,
           "isBlackBoxed": false,
+          "isPrettyPrinted": false,
+          "isWasm": false,
+          "loadedState": "unloaded",
+          "relativeUrl": "foo-view.js",
+          "text": "",
           "url": "foo-view.js",
         },
-        "toggleFrameworkGrouping": [MockFunction],
+        "this": Object {},
+        "thread": "FakeThread",
       }
     }
     options={
       Object {
         "shouldMapDisplayName": true,
       }
     }
   />
@@ -222,27 +395,50 @@ exports[`Frame user frame 1`] = `
   >
      
   </span>
   <FrameLocation
     displayFullUrl={false}
     frame={
       Object {
         "displayName": "renderFoo",
-        "frameworkGroupingOn": false,
-        "id": 1,
-        "library": false,
+        "generatedLocation": Object {
+          "line": 10,
+          "sourceId": "source",
+        },
+        "id": "1",
         "location": Object {
           "line": 10,
+          "sourceId": "source",
+        },
+        "scope": Object {
+          "actor": "scope-actor",
+          "bindings": Object {
+            "arguments": Array [],
+            "variables": Object {},
+          },
+          "function": null,
+          "object": null,
+          "parent": null,
+          "type": "block",
         },
         "source": Object {
+          "contentType": "text/javascript",
+          "id": "source",
+          "introductionUrl": null,
           "isBlackBoxed": false,
+          "isPrettyPrinted": false,
+          "isWasm": false,
+          "loadedState": "unloaded",
+          "relativeUrl": "foo-view.js",
+          "text": "",
           "url": "foo-view.js",
         },
-        "toggleFrameworkGrouping": [MockFunction],
+        "this": Object {},
+        "thread": "FakeThread",
       }
     }
   />
   <br
     className="clipboard-only"
   />
 </div>
 `;
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/tests/__snapshots__/Frames.spec.js.snap
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/tests/__snapshots__/Frames.spec.js.snap
@@ -7,67 +7,185 @@ exports[`Frames Blackboxed Frames filter
   <div
     role="list"
   >
     <Frame
       copyStackTrace={[Function]}
       disableContextMenu={false}
       frame={
         Object {
-          "id": 1,
+          "displayName": "display-1",
+          "generatedLocation": Object {
+            "line": 4,
+            "sourceId": "1",
+          },
+          "id": "1",
           "location": Object {
+            "line": 4,
             "sourceId": "1",
           },
+          "scope": Object {
+            "actor": "scope-actor",
+            "bindings": Object {
+              "arguments": Array [],
+              "variables": Object {},
+            },
+            "function": null,
+            "object": null,
+            "parent": null,
+            "type": "block",
+          },
           "source": Object {
+            "contentType": "text/javascript",
             "id": "1",
+            "introductionUrl": null,
+            "isBlackBoxed": false,
+            "isPrettyPrinted": false,
+            "isWasm": false,
+            "loadedState": "unloaded",
+            "relativeUrl": "url",
+            "text": "",
+            "url": "url",
           },
+          "this": Object {},
+          "thread": "FakeThread",
         }
       }
       frameworkGroupingOn={false}
       hideLocation={false}
       key="1"
       selectFrame={[MockFunction]}
       selectable={false}
       selectedFrame={
         Object {
-          "id": 1,
+          "displayName": "display-1",
+          "generatedLocation": Object {
+            "line": 4,
+            "sourceId": "1",
+          },
+          "id": "1",
           "location": Object {
+            "line": 4,
             "sourceId": "1",
           },
+          "scope": Object {
+            "actor": "scope-actor",
+            "bindings": Object {
+              "arguments": Array [],
+              "variables": Object {},
+            },
+            "function": null,
+            "object": null,
+            "parent": null,
+            "type": "block",
+          },
+          "source": Object {
+            "contentType": "text/javascript",
+            "id": "1",
+            "introductionUrl": null,
+            "isBlackBoxed": false,
+            "isPrettyPrinted": false,
+            "isWasm": false,
+            "loadedState": "unloaded",
+            "relativeUrl": "url",
+            "text": "",
+            "url": "url",
+          },
+          "this": Object {},
+          "thread": "FakeThread",
         }
       }
       shouldMapDisplayName={true}
       toggleBlackBox={[MockFunction]}
       toggleFrameworkGrouping={[Function]}
     />
     <Frame
       copyStackTrace={[Function]}
       disableContextMenu={false}
       frame={
         Object {
-          "id": 3,
+          "displayName": "display-3",
+          "generatedLocation": Object {
+            "line": 4,
+            "sourceId": "1",
+          },
+          "id": "3",
           "location": Object {
+            "line": 4,
             "sourceId": "1",
           },
+          "scope": Object {
+            "actor": "scope-actor",
+            "bindings": Object {
+              "arguments": Array [],
+              "variables": Object {},
+            },
+            "function": null,
+            "object": null,
+            "parent": null,
+            "type": "block",
+          },
           "source": Object {
+            "contentType": "text/javascript",
             "id": "1",
+            "introductionUrl": null,
+            "isBlackBoxed": false,
+            "isPrettyPrinted": false,
+            "isWasm": false,
+            "loadedState": "unloaded",
+            "relativeUrl": "url",
+            "text": "",
+            "url": "url",
           },
+          "this": Object {},
+          "thread": "FakeThread",
         }
       }
       frameworkGroupingOn={false}
       hideLocation={false}
       key="3"
       selectFrame={[MockFunction]}
       selectable={false}
       selectedFrame={
         Object {
-          "id": 1,
+          "displayName": "display-1",
+          "generatedLocation": Object {
+            "line": 4,
+            "sourceId": "1",
+          },
+          "id": "1",
           "location": Object {
+            "line": 4,
             "sourceId": "1",
           },
+          "scope": Object {
+            "actor": "scope-actor",
+            "bindings": Object {
+              "arguments": Array [],
+              "variables": Object {},
+            },
+            "function": null,
+            "object": null,
+            "parent": null,
+            "type": "block",
+          },
+          "source": Object {
+            "contentType": "text/javascript",
+            "id": "1",
+            "introductionUrl": null,
+            "isBlackBoxed": false,
+            "isPrettyPrinted": false,
+            "isWasm": false,
+            "loadedState": "unloaded",
+            "relativeUrl": "url",
+            "text": "",
+            "url": "url",
+          },
+          "this": Object {},
+          "thread": "FakeThread",
         }
       }
       shouldMapDisplayName={true}
       toggleBlackBox={[MockFunction]}
       toggleFrameworkGrouping={[Function]}
     />
   </div>
 </div>
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/tests/__snapshots__/Group.spec.js.snap
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Frames/tests/__snapshots__/Group.spec.js.snap
@@ -2,28 +2,63 @@
 
 exports[`Group displays a group 1`] = `
 <div
   className="frames-group"
   onContextMenu={[Function]}
 >
   <div
     className="group"
+    key="frame"
     onClick={[Function]}
     role="listitem"
     tabIndex={0}
     title="Show Back frames"
   >
     <FrameIndent />
     <FrameLocation
       expanded={false}
       frame={
         Object {
           "displayName": "foo",
+          "generatedLocation": Object {
+            "line": 4,
+            "sourceId": "source",
+          },
+          "id": "frame",
           "library": "Back",
+          "location": Object {
+            "line": 4,
+            "sourceId": "source",
+          },
+          "scope": Object {
+            "actor": "scope-actor",
+            "bindings": Object {
+              "arguments": Array [],
+              "variables": Object {},
+            },
+            "function": null,
+            "object": null,
+            "parent": null,
+            "type": "block",
+          },
+          "source": Object {
+            "contentType": "text/javascript",
+            "id": "source",
+            "introductionUrl": null,
+            "isBlackBoxed": false,
+            "isPrettyPrinted": false,
+            "isWasm": false,
+            "loadedState": "unloaded",
+            "relativeUrl": "url",
+            "text": "",
+            "url": "url",
+          },
+          "this": Object {},
+          "thread": "FakeThread",
         }
       }
     />
     <span
       className="clipboard-only"
     >
        
     </span>
@@ -48,24 +83,51 @@ exports[`Group passes the getFrameTitle 
     title="Collapse Back frames"
   >
     <FrameIndent />
     <FrameLocation
       expanded={true}
       frame={
         Object {
           "displayName": "renderFoo",
-          "id": 1,
+          "generatedLocation": Object {
+            "line": 55,
+            "sourceId": "source",
+          },
+          "id": "1",
           "library": "Back",
           "location": Object {
             "line": 55,
+            "sourceId": "source",
+          },
+          "scope": Object {
+            "actor": "scope-actor",
+            "bindings": Object {
+              "arguments": Array [],
+              "variables": Object {},
+            },
+            "function": null,
+            "object": null,
+            "parent": null,
+            "type": "block",
           },
           "source": Object {
+            "contentType": "text/javascript",
+            "id": "source",
+            "introductionUrl": null,
+            "isBlackBoxed": false,
+            "isPrettyPrinted": false,
+            "isWasm": false,
+            "loadedState": "unloaded",
+            "relativeUrl": "http://myfile.com/mahscripts.js",
+            "text": "",
             "url": "http://myfile.com/mahscripts.js",
           },
+          "this": Object {},
+          "thread": "FakeThread",
         }
       }
     />
     <span
       className="clipboard-only"
     >
        
     </span>
@@ -79,91 +141,289 @@ exports[`Group passes the getFrameTitle 
     <FrameIndent />
     <Frame
       copyStackTrace={[MockFunction]}
       disableContextMenu={false}
       displayFullUrl={false}
       frame={
         Object {
           "displayName": "renderFoo",
-          "id": 1,
+          "generatedLocation": Object {
+            "line": 55,
+            "sourceId": "source",
+          },
+          "id": "1",
           "library": "Back",
           "location": Object {
             "line": 55,
+            "sourceId": "source",
+          },
+          "scope": Object {
+            "actor": "scope-actor",
+            "bindings": Object {
+              "arguments": Array [],
+              "variables": Object {},
+            },
+            "function": null,
+            "object": null,
+            "parent": null,
+            "type": "block",
           },
           "source": Object {
+            "contentType": "text/javascript",
+            "id": "source",
+            "introductionUrl": null,
+            "isBlackBoxed": false,
+            "isPrettyPrinted": false,
+            "isWasm": false,
+            "loadedState": "unloaded",
+            "relativeUrl": "http://myfile.com/mahscripts.js",
+            "text": "",
             "url": "http://myfile.com/mahscripts.js",
           },
+          "this": Object {},
+          "thread": "FakeThread",
         }
       }
       frameworkGroupingOn={true}
       getFrameTitle={[Function]}
       hideLocation={true}
       key="1"
       selectFrame={[MockFunction]}
       selectable={true}
-      selectedFrame={Object {}}
+      selectedFrame={
+        Object {
+          "displayName": "foo",
+          "generatedLocation": Object {
+            "line": 4,
+            "sourceId": "source",
+          },
+          "id": "frame",
+          "library": "Back",
+          "location": Object {
+            "line": 4,
+            "sourceId": "source",
+          },
+          "scope": Object {
+            "actor": "scope-actor",
+            "bindings": Object {
+              "arguments": Array [],
+              "variables": Object {},
+            },
+            "function": null,
+            "object": null,
+            "parent": null,
+            "type": "block",
+          },
+          "source": Object {
+            "contentType": "text/javascript",
+            "id": "source",
+            "introductionUrl": null,
+            "isBlackBoxed": false,
+            "isPrettyPrinted": false,
+            "isWasm": false,
+            "loadedState": "unloaded",
+            "relativeUrl": "url",
+            "text": "",
+            "url": "url",
+          },
+          "this": Object {},
+          "thread": "FakeThread",
+        }
+      }
       shouldMapDisplayName={false}
       toggleBlackBox={[MockFunction]}
       toggleFrameworkGrouping={[MockFunction]}
     />
     <FrameIndent />
     <Frame
       copyStackTrace={[MockFunction]}
       disableContextMenu={false}
       displayFullUrl={false}
       frame={
         Object {
           "displayName": "a",
-          "id": 2,
+          "generatedLocation": Object {
+            "line": 55,
+            "sourceId": "source",
+          },
+          "id": "2",
           "library": "Back",
           "location": Object {
             "line": 55,
+            "sourceId": "source",
+          },
+          "scope": Object {
+            "actor": "scope-actor",
+            "bindings": Object {
+              "arguments": Array [],
+              "variables": Object {},
+            },
+            "function": null,
+            "object": null,
+            "parent": null,
+            "type": "block",
           },
           "source": Object {
+            "contentType": "text/javascript",
+            "id": "source",
+            "introductionUrl": null,
+            "isBlackBoxed": false,
+            "isPrettyPrinted": false,
+            "isWasm": false,
+            "loadedState": "unloaded",
+            "relativeUrl": "http://myfile.com/back.js",
+            "text": "",
             "url": "http://myfile.com/back.js",
           },
+          "this": Object {},
+          "thread": "FakeThread",
         }
       }
       frameworkGroupingOn={true}
       getFrameTitle={[Function]}
       hideLocation={true}
       key="2"
       selectFrame={[MockFunction]}
       selectable={true}
-      selectedFrame={Object {}}
+      selectedFrame={
+        Object {
+          "displayName": "foo",
+          "generatedLocation": Object {
+            "line": 4,
+            "sourceId": "source",
+          },
+          "id": "frame",
+          "library": "Back",
+          "location": Object {
+            "line": 4,
+            "sourceId": "source",
+          },
+          "scope": Object {
+            "actor": "scope-actor",
+            "bindings": Object {
+              "arguments": Array [],
+              "variables": Object {},
+            },
+            "function": null,
+            "object": null,
+            "parent": null,
+            "type": "block",
+          },
+          "source": Object {
+            "contentType": "text/javascript",
+            "id": "source",
+            "introductionUrl": null,
+            "isBlackBoxed": false,
+            "isPrettyPrinted": false,
+            "isWasm": false,
+            "loadedState": "unloaded",
+            "relativeUrl": "url",
+            "text": "",
+            "url": "url",
+          },
+          "this": Object {},
+          "thread": "FakeThread",
+        }
+      }
       shouldMapDisplayName={false}
       toggleBlackBox={[MockFunction]}
       toggleFrameworkGrouping={[MockFunction]}
     />
     <FrameIndent />
     <Frame
       copyStackTrace={[MockFunction]}
       disableContextMenu={false}
       displayFullUrl={false}
       frame={
         Object {
           "displayName": "b",
-          "id": 3,
+          "generatedLocation": Object {
+            "line": 55,
+            "sourceId": "source",
+          },
+          "id": "3",
           "library": "Back",
           "location": Object {
             "line": 55,
+            "sourceId": "source",
+          },
+          "scope": Object {
+            "actor": "scope-actor",
+            "bindings": Object {
+              "arguments": Array [],
+              "variables": Object {},
+            },
+            "function": null,
+            "object": null,
+            "parent": null,
+            "type": "block",
           },
           "source": Object {
+            "contentType": "text/javascript",
+            "id": "source",
+            "introductionUrl": null,
+            "isBlackBoxed": false,
+            "isPrettyPrinted": false,
+            "isWasm": false,
+            "loadedState": "unloaded",
+            "relativeUrl": "http://myfile.com/back.js",
+            "text": "",
             "url": "http://myfile.com/back.js",
           },
+          "this": Object {},
+          "thread": "FakeThread",
         }
       }
       frameworkGroupingOn={true}
       getFrameTitle={[Function]}
       hideLocation={true}
       key="3"
       selectFrame={[MockFunction]}
       selectable={true}
-      selectedFrame={Object {}}
+      selectedFrame={
+        Object {
+          "displayName": "foo",
+          "generatedLocation": Object {
+            "line": 4,
+            "sourceId": "source",
+          },
+          "id": "frame",
+          "library": "Back",
+          "location": Object {
+            "line": 4,
+            "sourceId": "source",
+          },
+          "scope": Object {
+            "actor": "scope-actor",
+            "bindings": Object {
+              "arguments": Array [],
+              "variables": Object {},
+            },
+            "function": null,
+            "object": null,
+            "parent": null,
+            "type": "block",
+          },
+          "source": Object {
+            "contentType": "text/javascript",
+            "id": "source",
+            "introductionUrl": null,
+            "isBlackBoxed": false,
+            "isPrettyPrinted": false,
+            "isWasm": false,
+            "loadedState": "unloaded",
+            "relativeUrl": "url",
+            "text": "",
+            "url": "url",
+          },
+          "this": Object {},
+          "thread": "FakeThread",
+        }
+      }
       shouldMapDisplayName={false}
       toggleBlackBox={[MockFunction]}
       toggleFrameworkGrouping={[MockFunction]}
     />
   </div>
 </div>
 `;
 
@@ -180,25 +440,52 @@ exports[`Group renders group with anonym
     tabIndex={0}
     title="Show Back frames"
   >
     <FrameIndent />
     <FrameLocation
       expanded={false}
       frame={
         Object {
-          "displayName": "",
-          "id": 1,
+          "displayName": "display-1",
+          "generatedLocation": Object {
+            "line": 55,
+            "sourceId": "source",
+          },
+          "id": "1",
           "library": "Back",
           "location": Object {
             "line": 55,
+            "sourceId": "source",
+          },
+          "scope": Object {
+            "actor": "scope-actor",
+            "bindings": Object {
+              "arguments": Array [],
+              "variables": Object {},
+            },
+            "function": null,
+            "object": null,
+            "parent": null,
+            "type": "block",
           },
           "source": Object {
+            "contentType": "text/javascript",
+            "id": "source",
+            "introductionUrl": null,
+            "isBlackBoxed": false,
+            "isPrettyPrinted": false,
+            "isWasm": false,
+            "loadedState": "unloaded",
+            "relativeUrl": "http://myfile.com/mahscripts.js",
+            "text": "",
             "url": "http://myfile.com/mahscripts.js",
           },
+          "this": Object {},
+          "thread": "FakeThread",
         }
       }
     />
     <span
       className="clipboard-only"
     >
        
     </span>
@@ -222,25 +509,52 @@ exports[`Group renders group with anonym
     tabIndex={0}
     title="Collapse Back frames"
   >
     <FrameIndent />
     <FrameLocation
       expanded={true}
       frame={
         Object {
-          "displayName": "",
-          "id": 1,
+          "displayName": "display-1",
+          "generatedLocation": Object {
+            "line": 55,
+            "sourceId": "source",
+          },
+          "id": "1",
           "library": "Back",
           "location": Object {
             "line": 55,
+            "sourceId": "source",
+          },
+          "scope": Object {
+            "actor": "scope-actor",
+            "bindings": Object {
+              "arguments": Array [],
+              "variables": Object {},
+            },
+            "function": null,
+            "object": null,
+            "parent": null,
+            "type": "block",
           },
           "source": Object {
+            "contentType": "text/javascript",
+            "id": "source",
+            "introductionUrl": null,
+            "isBlackBoxed": false,
+            "isPrettyPrinted": false,
+            "isWasm": false,
+            "loadedState": "unloaded",
+            "relativeUrl": "http://myfile.com/mahscripts.js",
+            "text": "",
             "url": "http://myfile.com/mahscripts.js",
           },
+          "this": Object {},
+          "thread": "FakeThread",
         }
       }
     />
     <span
       className="clipboard-only"
     >
        
     </span>
@@ -253,88 +567,286 @@ exports[`Group renders group with anonym
   >
     <FrameIndent />
     <Frame
       copyStackTrace={[MockFunction]}
       disableContextMenu={false}
       displayFullUrl={false}
       frame={
         Object {
-          "displayName": "",
-          "id": 1,
+          "displayName": "display-1",
+          "generatedLocation": Object {
+            "line": 55,
+            "sourceId": "source",
+          },
+          "id": "1",
           "library": "Back",
           "location": Object {
             "line": 55,
+            "sourceId": "source",
+          },
+          "scope": Object {
+            "actor": "scope-actor",
+            "bindings": Object {
+              "arguments": Array [],
+              "variables": Object {},
+            },
+            "function": null,
+            "object": null,
+            "parent": null,
+            "type": "block",
           },
           "source": Object {
+            "contentType": "text/javascript",
+            "id": "source",
+            "introductionUrl": null,
+            "isBlackBoxed": false,
+            "isPrettyPrinted": false,
+            "isWasm": false,
+            "loadedState": "unloaded",
+            "relativeUrl": "http://myfile.com/mahscripts.js",
+            "text": "",
             "url": "http://myfile.com/mahscripts.js",
           },
+          "this": Object {},
+          "thread": "FakeThread",
         }
       }
       frameworkGroupingOn={true}
       hideLocation={true}
       key="1"
       selectFrame={[MockFunction]}
       selectable={true}
-      selectedFrame={Object {}}
+      selectedFrame={
+        Object {
+          "displayName": "foo",
+          "generatedLocation": Object {
+            "line": 4,
+            "sourceId": "source",
+          },
+          "id": "frame",
+          "library": "Back",
+          "location": Object {
+            "line": 4,
+            "sourceId": "source",
+          },
+          "scope": Object {
+            "actor": "scope-actor",
+            "bindings": Object {
+              "arguments": Array [],
+              "variables": Object {},
+            },
+            "function": null,
+            "object": null,
+            "parent": null,
+            "type": "block",
+          },
+          "source": Object {
+            "contentType": "text/javascript",
+            "id": "source",
+            "introductionUrl": null,
+            "isBlackBoxed": false,
+            "isPrettyPrinted": false,
+            "isWasm": false,
+            "loadedState": "unloaded",
+            "relativeUrl": "url",
+            "text": "",
+            "url": "url",
+          },
+          "this": Object {},
+          "thread": "FakeThread",
+        }
+      }
       shouldMapDisplayName={false}
       toggleBlackBox={[MockFunction]}
       toggleFrameworkGrouping={[MockFunction]}
     />
     <FrameIndent />
     <Frame
       copyStackTrace={[MockFunction]}
       disableContextMenu={false}
       displayFullUrl={false}
       frame={
         Object {
-          "displayName": "",
-          "id": 2,
+          "displayName": "display-2",
+          "generatedLocation": Object {
+            "line": 55,
+            "sourceId": "source",
+          },
+          "id": "2",
           "library": "Back",
           "location": Object {
             "line": 55,
+            "sourceId": "source",
+          },
+          "scope": Object {
+            "actor": "scope-actor",
+            "bindings": Object {
+              "arguments": Array [],
+              "variables": Object {},
+            },
+            "function": null,
+            "object": null,
+            "parent": null,
+            "type": "block",
           },
           "source": Object {
+            "contentType": "text/javascript",
+            "id": "source",
+            "introductionUrl": null,
+            "isBlackBoxed": false,
+            "isPrettyPrinted": false,
+            "isWasm": false,
+            "loadedState": "unloaded",
+            "relativeUrl": "http://myfile.com/back.js",
+            "text": "",
             "url": "http://myfile.com/back.js",
           },
+          "this": Object {},
+          "thread": "FakeThread",
         }
       }
       frameworkGroupingOn={true}
       hideLocation={true}
       key="2"
       selectFrame={[MockFunction]}
       selectable={true}
-      selectedFrame={Object {}}
+      selectedFrame={
+        Object {
+          "displayName": "foo",
+          "generatedLocation": Object {
+            "line": 4,
+            "sourceId": "source",
+          },
+          "id": "frame",
+          "library": "Back",
+          "location": Object {
+            "line": 4,
+            "sourceId": "source",
+          },
+          "scope": Object {
+            "actor": "scope-actor",
+            "bindings": Object {
+              "arguments": Array [],
+              "variables": Object {},
+            },
+            "function": null,
+            "object": null,
+            "parent": null,
+            "type": "block",
+          },
+          "source": Object {
+            "contentType": "text/javascript",
+            "id": "source",
+            "introductionUrl": null,
+            "isBlackBoxed": false,
+            "isPrettyPrinted": false,
+            "isWasm": false,
+            "loadedState": "unloaded",
+            "relativeUrl": "url",
+            "text": "",
+            "url": "url",
+          },
+          "this": Object {},
+          "thread": "FakeThread",
+        }
+      }
       shouldMapDisplayName={false}
       toggleBlackBox={[MockFunction]}
       toggleFrameworkGrouping={[MockFunction]}
     />
     <FrameIndent />
     <Frame
       copyStackTrace={[MockFunction]}
       disableContextMenu={false}
       displayFullUrl={false}
       frame={
         Object {
-          "displayName": "",
-          "id": 3,
+          "displayName": "display-3",
+          "generatedLocation": Object {
+            "line": 55,
+            "sourceId": "source",
+          },
+          "id": "3",
           "library": "Back",
           "location": Object {
             "line": 55,
+            "sourceId": "source",
+          },
+          "scope": Object {
+            "actor": "scope-actor",
+            "bindings": Object {
+              "arguments": Array [],
+              "variables": Object {},
+            },
+            "function": null,
+            "object": null,
+            "parent": null,
+            "type": "block",
           },
           "source": Object {
+            "contentType": "text/javascript",
+            "id": "source",
+            "introductionUrl": null,
+            "isBlackBoxed": false,
+            "isPrettyPrinted": false,
+            "isWasm": false,
+            "loadedState": "unloaded",
+            "relativeUrl": "http://myfile.com/back.js",
+            "text": "",
             "url": "http://myfile.com/back.js",
           },
+          "this": Object {},
+          "thread": "FakeThread",
         }
       }
       frameworkGroupingOn={true}
       hideLocation={true}
       key="3"
       selectFrame={[MockFunction]}
       selectable={true}
-      selectedFrame={Object {}}
+      selectedFrame={
+        Object {
+          "displayName": "foo",
+          "generatedLocation": Object {
+            "line": 4,
+            "sourceId": "source",
+          },
+          "id": "frame",
+          "library": "Back",
+          "location": Object {
+            "line": 4,
+            "sourceId": "source",
+          },
+          "scope": Object {
+            "actor": "scope-actor",
+            "bindings": Object {
+              "arguments": Array [],
+              "variables": Object {},
+            },
+            "function": null,
+            "object": null,
+            "parent": null,
+            "type": "block",
+          },
+          "source": Object {
+            "contentType": "text/javascript",
+            "id": "source",
+            "introductionUrl": null,
+            "isBlackBoxed": false,
+            "isPrettyPrinted": false,
+            "isWasm": false,
+            "loadedState": "unloaded",
+            "relativeUrl": "url",
+            "text": "",
+            "url": "url",
+          },
+          "this": Object {},
+          "thread": "FakeThread",
+        }
+      }
       shouldMapDisplayName={false}
       toggleBlackBox={[MockFunction]}
       toggleFrameworkGrouping={[MockFunction]}
     />
   </div>
 </div>
 `;
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/XHRBreakpoints.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/XHRBreakpoints.js
@@ -54,16 +54,26 @@ class XHRBreakpoints extends Component<P
       editing: false,
       inputValue: "",
       inputMethod: "",
       focused: false,
       editIndex: -1
     };
   }
 
+  componentDidMount() {
+    const { showInput } = this.props;
+
+    // Ensures that the input is focused when the "+"
+    // is clicked while the panel is collapsed
+    if (this._input && showInput) {
+      this._input.focus();
+    }
+  }
+
   componentDidUpdate(prevProps, prevState) {
     const input = this._input;
 
     if (!input) {
       return;
     }
 
     if (!prevState.editing && this.state.editing) {
--- a/devtools/client/debugger/new/src/components/WelcomeBox.css
+++ b/devtools/client/debugger/new/src/components/WelcomeBox.css
@@ -1,23 +1,20 @@
 /* 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/>. */
 
 .welcomebox {
+  position: absolute;
+  top: var(--editor-header-height);
+  left: 0;
+  bottom: 1px;
   width: calc(100% - 1px);
-
-  /* Offsetting it by 30px for the sources-header area */
-  height: calc(100% - 30px);
-  position: absolute;
-  top: 30px;
-  left: 0;
   padding: 50px 0 0 0;
   text-align: center;
-  font-size: 1.25em;
   background-color: var(--theme-toolbar-background);
   font-weight: lighter;
   z-index: 10;
   user-select: none;
 }
 
 .theme-dark .welcomebox {
   background-color: var(--theme-body-background);
@@ -31,16 +28,17 @@
   offset-inline-start: auto;
   inset-inline-start: auto;
   bottom: 0;
 }
 
 .alignlabel {
   display: flex;
   white-space: nowrap;
+  font-size: 1.25em;
 }
 
 .shortcutKeys {
   font-family: Courier;
 }
 
 .shortcutKey,
 .shortcutLabel {
--- a/devtools/client/debugger/new/src/components/WelcomeBox.js
+++ b/devtools/client/debugger/new/src/components/WelcomeBox.js
@@ -30,17 +30,17 @@ export class WelcomeBox extends Componen
     const { horizontal, endPanelCollapsed, togglePaneCollapse } = this.props;
     if (horizontal) {
       return;
     }
 
     return (
       <PaneToggleButton
         position="end"
-        collapsed={!endPanelCollapsed}
+        collapsed={endPanelCollapsed}
         horizontal={horizontal}
         handleClick={togglePaneCollapse}
       />
     );
   }
 
   render() {
     const searchSourcesShortcut = formatKeyShortcut(
@@ -87,18 +87,18 @@ export class WelcomeBox extends Componen
               role="button"
               tabIndex="0"
               onClick={() => toggleShortcutsModal()}
             >
               <span className="shortcutKey">{allShortcutsShortcut}</span>
               <span className="shortcutLabel">{allShortcutsLabel}</span>
             </p>
           </div>
-          {this.renderToggleButton()}
         </div>
+        {this.renderToggleButton()}
       </div>
     );
   }
 }
 
 const mapStateToProps = state => ({
   endPanelCollapsed: getPaneCollapse(state, "end")
 });
--- a/devtools/client/debugger/new/src/components/shared/AccessibleImage.css
+++ b/devtools/client/debugger/new/src/components/shared/AccessibleImage.css
@@ -1,9 +1,9 @@
 .img {
   /* default height an width which will likely be overrode */
   width: 12px;
   height: 12px;
   /* makes span appear like an image */
   display: inline-block;
-  background: var(--theme-body-color);
+  background: var(--theme-icon-color);
   mask-size: 100%;
 }
--- a/devtools/client/debugger/new/src/components/shared/Button/PaneToggleButton.js
+++ b/devtools/client/debugger/new/src/components/shared/Button/PaneToggleButton.js
@@ -18,28 +18,30 @@ type Props = {
 
 class PaneToggleButton extends PureComponent<Props> {
   static defaultProps = {
     horizontal: false
   };
 
   render() {
     const { position, collapsed, horizontal, handleClick } = this.props;
-    const title = !collapsed
+    const title = collapsed
       ? L10N.getStr("expandPanes")
       : L10N.getStr("collapsePanes");
 
     return (
       <CommandBarButton
         className={classnames("toggle-button", position, {
           collapsed,
           vertical: !horizontal
         })}
-        onClick={() => handleClick(position, collapsed)}
+        onClick={() => handleClick(position, !collapsed)}
         title={title}
       >
-        <AccessibleImage className="toggle-panes" />
+        <AccessibleImage
+          className={collapsed ? "pane-expand" : "pane-collapse"}
+        />
       </CommandBarButton>
     );
   }
 }
 
 export default PaneToggleButton;
--- a/devtools/client/debugger/new/src/components/shared/Button/index.js
+++ b/devtools/client/debugger/new/src/components/shared/Button/index.js
@@ -1,9 +1,11 @@
 /* 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 CloseButton from "./CloseButton";
 import CommandBarButton, { debugBtn } from "./CommandBarButton";
 import PaneToggleButton from "./PaneToggleButton";
 
 export { CloseButton, CommandBarButton, debugBtn, PaneToggleButton };
--- a/devtools/client/debugger/new/src/components/shared/Button/styles/CommandBarButton.css
+++ b/devtools/client/debugger/new/src/components/shared/Button/styles/CommandBarButton.css
@@ -18,16 +18,20 @@
   opacity: 0.8;
   cursor: default;
 }
 
 .command-bar-button:not(.disabled):hover {
   background: var(--theme-toolbar-background-hover);
 }
 
+.theme-dark .command-bar-button:not(.disabled):hover {
+  background: var(--theme-toolbar-hover);
+}
+
 :root.theme-dark .command-bar-button {
   color: var(--theme-body-color);
 }
 
 .command-bar-button > * {
   width: 16px;
   height: 16px;
   display: inline-block;
--- a/devtools/client/debugger/new/src/components/shared/Button/styles/PaneToggleButton.css
+++ b/devtools/client/debugger/new/src/components/shared/Button/styles/PaneToggleButton.css
@@ -1,42 +1,29 @@
 /* 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/>. */
 
 .toggle-button {
-  transform: translate(0, 0px);
-  transition: transform 0.25s ease-in-out;
-  padding: 5px;
-  height: inherit;
+  padding: 4px 6px;
 }
 
 .toggle-button .img {
-  fill: var(--theme-comment);
-  vertical-align: 0;
-}
-
-:root.theme-dark .toggle-button .img {
-  fill: var(--theme-comment-alt);
+  vertical-align: middle;
 }
 
 .toggle-button.end {
   margin-inline-end: 0px;
   margin-inline-start: auto;
 }
 
 .toggle-button.start {
   margin-inline-start: 0px;
 }
 
-html:not([dir="rtl"]) .toggle-button.end .img,
-html[dir="rtl"] .toggle-button.start .img {
-  transform: rotate(180deg);
+html[dir="rtl"] .toggle-button.start .img,
+html[dir="ltr"] .toggle-button.end:not(.vertical) .img {
+  transform: scaleX(-1);
 }
 
-html .toggle-button.end.vertical .img {
+.toggle-button.end.vertical .img {
   transform: rotate(-90deg);
 }
-
-.toggle-button.start.collapsed,
-.toggle-button.end.collapsed {
-  transform: rotate(180deg);
-}
--- a/devtools/client/debugger/new/src/components/shared/Button/tests/CloseButton.spec.js
+++ b/devtools/client/debugger/new/src/components/shared/Button/tests/CloseButton.spec.js
@@ -6,17 +6,19 @@
 
 import React from "react";
 import { shallow } from "enzyme";
 import { CloseButton } from "../";
 
 describe("CloseButton", () => {
   it("renders with tooltip", () => {
     const tooltip = "testTooltip";
-    const wrapper = shallow(<CloseButton tooltip={tooltip} />);
+    const wrapper = shallow(
+      <CloseButton tooltip={tooltip} handleClick={() => {}} />
+    );
     expect(wrapper).toMatchSnapshot();
   });
 
   it("handles click event", () => {
     const handleClickSpy = jest.fn();
     const wrapper = shallow(<CloseButton handleClick={handleClickSpy} />);
     wrapper.simulate("click");
     expect(handleClickSpy).toBeCalled();
--- a/devtools/client/debugger/new/src/components/shared/Button/tests/CommandBarButton.spec.js
+++ b/devtools/client/debugger/new/src/components/shared/Button/tests/CommandBarButton.spec.js
@@ -5,23 +5,27 @@
 // @flow
 
 import React from "react";
 import { shallow } from "enzyme";
 import { CommandBarButton, debugBtn } from "../";
 
 describe("CommandBarButton", () => {
   it("renders", () => {
-    const wrapper = shallow(<CommandBarButton />);
+    const wrapper = shallow(
+      <CommandBarButton children={([]: any)} className={""} />
+    );
     expect(wrapper).toMatchSnapshot();
   });
 
   it("renders children", () => {
     const children = [1, 2, 3, 4];
-    const wrapper = shallow(<CommandBarButton children={children} />);
+    const wrapper = shallow(
+      <CommandBarButton children={(children: any)} className={""} />
+    );
     expect(wrapper.find("button").children()).toHaveLength(4);
   });
 });
 
 describe("debugBtn", () => {
   it("renders", () => {
     const wrapper = shallow(<debugBtn />);
     expect(wrapper).toMatchSnapshot();
--- a/devtools/client/debugger/new/src/components/shared/Button/tests/PaneToggleButton.spec.js
+++ b/devtools/client/debugger/new/src/components/shared/Button/tests/PaneToggleButton.spec.js
@@ -5,17 +5,23 @@
 // @flow
 
 import React from "react";
 import { shallow } from "enzyme";
 import { PaneToggleButton } from "../";
 
 describe("PaneToggleButton", () => {
   const handleClickSpy = jest.fn();
-  const wrapper = shallow(<PaneToggleButton handleClick={handleClickSpy} />);
+  const wrapper = shallow(
+    <PaneToggleButton
+      handleClick={handleClickSpy}
+      collapsed={false}
+      position={""}
+    />
+  );
 
   it("renders default", () => {
     expect(wrapper.hasClass("vertical")).toBe(true);
     expect(wrapper).toMatchSnapshot();
   });
 
   it("toggles horizontal class", () => {
     wrapper.setProps({ horizontal: true });
@@ -34,14 +40,14 @@ describe("PaneToggleButton", () => {
 
   it("toggles end position ", () => {
     wrapper.setProps({ position: "end" });
     expect(wrapper.hasClass("end")).toBe(true);
   });
 
   it("handleClick is called", () => {
     const position = "testPosition";
-    const collapsed = "testCollapsed";
+    const collapsed = false;
     wrapper.setProps({ position, collapsed });
     wrapper.simulate("click");
-    expect(handleClickSpy).toBeCalledWith(position, collapsed);
+    expect(handleClickSpy).toBeCalledWith(position, true);
   });
 });
--- a/devtools/client/debugger/new/src/components/shared/Button/tests/__snapshots__/CloseButton.spec.js.snap
+++ b/devtools/client/debugger/new/src/components/shared/Button/tests/__snapshots__/CloseButton.spec.js.snap
@@ -1,12 +1,13 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`CloseButton renders with tooltip 1`] = `
 <button
   className="close-btn"
+  onClick={[Function]}
   title="testTooltip"
 >
   <AccessibleImage
     className="close"
   />
 </button>
 `;
--- a/devtools/client/debugger/new/src/components/shared/Button/tests/__snapshots__/PaneToggleButton.spec.js.snap
+++ b/devtools/client/debugger/new/src/components/shared/Button/tests/__snapshots__/PaneToggleButton.spec.js.snap
@@ -1,13 +1,13 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`PaneToggleButton renders default 1`] = `
 <CommandBarButton
   className="toggle-button vertical"
   onClick={[Function]}
-  title="Expand panes"
+  title="Collapse panes"
 >
   <AccessibleImage
-    className="toggle-panes"
+    className="pane-collapse"
   />
 </CommandBarButton>
 `;
--- a/devtools/client/debugger/new/src/components/shared/ManagedTree.js
+++ b/devtools/client/debugger/new/src/components/shared/ManagedTree.js
@@ -35,18 +35,17 @@ type Props = {
 type State = {
   expanded: any
 };
 
 class ManagedTree extends Component<Props, State> {
   constructor(props: Props) {
     super(props);
     this.state = {
-      expanded: props.expanded || new Set(),
-      focusedItem: null
+      expanded: props.expanded || new Set()
     };
   }
 
   static defaultProps = {
     onFocus: () => {}
   };
 
   componentWillReceiveProps(nextProps: Props) {
--- a/devtools/client/debugger/new/src/components/shared/PreviewFunction.js
+++ b/devtools/client/debugger/new/src/components/shared/PreviewFunction.js
@@ -20,17 +20,17 @@ type FunctionType = {
   parameterNames?: string[]
 };
 
 type Props = { func: FunctionType };
 
 export default class PreviewFunction extends Component<Props> {
   renderFunctionName(func: FunctionType) {
     const { l10n } = this.context;
-    const name = formatDisplayName(func, undefined, l10n);
+    const name = formatDisplayName((func: any), undefined, l10n);
     return <span className="function-name">{name}</span>;
   }
 
   renderParams(func: FunctionType) {
     const { parameterNames = [] } = func;
     const params = parameterNames.filter(i => i).map(param => (
       <span className="param" key={param}>
         {param}
--- a/devtools/client/debugger/new/src/components/shared/Svg.css
+++ b/devtools/client/debugger/new/src/components/shared/Svg.css
@@ -203,18 +203,23 @@ span.img.marko {
   mask-size: 100%;
 }
 
 .img.extension {
   mask: url(/images/extension.svg) no-repeat;
   mask-size: 100%;
 }
 
-.img.toggle-panes {
-  mask: url(/images/toggle-panes.svg) no-repeat;
+.img.pane-collapse {
+  mask: url(/images/pane-collapse.svg) no-repeat;
+  mask-size: 100%;
+}
+
+.img.pane-expand {
+  mask: url(/images/pane-expand.svg) no-repeat;
   mask-size: 100%;
 }
 
 .img.file {
   mask: url(/images/file.svg) no-repeat;
   mask-size: 100%;
   width: 13px;
   height: 13px;
--- a/devtools/client/debugger/new/src/components/test/ProjectSearch.spec.js
+++ b/devtools/client/debugger/new/src/components/test/ProjectSearch.spec.js
@@ -60,16 +60,17 @@ const testResults = [
         type: "MATCH"
       },
       { match: "match5", value: "some thing match5", column: 40, type: "MATCH" }
     ]
   }
 ];
 
 const testMatch = {
+  type: "MATCH",
   match: "match1",
   value: "some thing match1",
   sourceId: "some-target/source42",
   line: 3,
   column: 30
 };
 
 function render(overrides = {}, mounted = false) {
@@ -193,62 +194,39 @@ describe("ProjectSearch", () => {
     const selectSpecificLocation = jest.fn();
     const component = render(
       {
         results: testResults,
         selectSpecificLocation
       },
       true
     );
-    component.instance().focusedItem = null;
+    component.instance().state.focusedItem = null;
     shortcuts.dispatch("Enter");
     expect(selectSpecificLocation).not.toHaveBeenCalled();
   });
 
   it("onEnterPress shortcut match", () => {
     const selectSpecificLocation = jest.fn();
     const component = render(
       {
         results: testResults,
         selectSpecificLocation
       },
       true
     );
-    component.instance().focusedItem = { match: testMatch, expanded: null };
+    component.instance().state.focusedItem = { ...testMatch };
     shortcuts.dispatch("Enter");
     expect(selectSpecificLocation).toHaveBeenCalledWith({
       sourceId: "some-target/source42",
       line: 3,
       column: 30
     });
   });
 
-  it("onEnterPress shortcut setExpanded", () => {
-    const selectSpecificLocation = jest.fn();
-    const component = render(
-      {
-        results: testResults,
-        selectSpecificLocation
-      },
-      true
-    );
-    const setExpanded = jest.fn();
-    const testFile = {
-      filepath: "testFilePath1",
-      matches: [testMatch]
-    };
-    component.instance().focusedItem = {
-      setExpanded,
-      file: testFile,
-      expanded: true
-    };
-    shortcuts.dispatch("Enter");
-    expect(setExpanded).toHaveBeenCalledWith(testFile, false);
-  });
-
   it("state.inputValue responds to prop.query changes", () => {
     const component = render({ query: "foo" });
     expect(component.state().inputValue).toEqual("foo");
     component.setProps({ query: "" });
     expect(component.state().inputValue).toEqual("");
   });
 
   describe("showErrorEmoji", () => {
--- a/devtools/client/debugger/new/src/components/test/__snapshots__/Outline.spec.js.snap
+++ b/devtools/client/debugger/new/src/components/test/__snapshots__/Outline.spec.js.snap
@@ -5,17 +5,17 @@ exports[`Outline renders a list of funct
   className="outline"
 >
   <div>
     <OutlineFilter
       filter=""
       updateFilter={[Function]}
     />
     <ul
-      className="outline-list"
+      className="outline-list devtools-monospace"
     >
       <li
         className="outline-list__element"
         key="my_example_function1:21:undefined"
         onClick={[Function]}
         onContextMenu={[Function]}
       >
         <span
@@ -72,17 +72,17 @@ exports[`Outline renders outline renders
   className="outline"
 >
   <div>
     <OutlineFilter
       filter=""
       updateFilter={[Function]}
     />
     <ul
-      className="outline-list"
+      className="outline-list devtools-monospace"
     >
       <div
         className="outline-list__class"
         key="x_klass"
       >
         <h2
           onClick={[Function]}
         >
@@ -199,17 +199,17 @@ exports[`Outline renders outline renders
   className="outline"
 >
   <div>
     <OutlineFilter
       filter=""
       updateFilter={[Function]}
     />
     <ul
-      className="outline-list"
+      className="outline-list devtools-monospace"
     >
       <div
         className="outline-list__class"
         key="x_klass"
       >
         <h2
           onClick={[Function]}
         >
@@ -326,17 +326,17 @@ exports[`Outline renders outline renders
   className="outline"
 >
   <div>
     <OutlineFilter
       filter=""
       updateFilter={[Function]}
     />
     <ul
-      className="outline-list"
+      className="outline-list devtools-monospace"
     >
       <li
         className="outline-list__element"
         key="my_example_function1:21:undefined"
         onClick={[Function]}
         onContextMenu={[Function]}
       >
         <span
@@ -413,17 +413,17 @@ exports[`Outline renders outline sorts f
   className="outline"
 >
   <div>
     <OutlineFilter
       filter=""
       updateFilter={[Function]}
     />
     <ul
-      className="outline-list"
+      className="outline-list devtools-monospace"
     >
       <li
         className="outline-list__element"
         key="a_function:70:undefined"
         onClick={[Function]}
         onContextMenu={[Function]}
       >
         <span
--- a/devtools/client/debugger/new/src/components/test/__snapshots__/ProjectSearch.spec.js.snap
+++ b/devtools/client/debugger/new/src/components/test/__snapshots__/ProjectSearch.spec.js.snap
@@ -195,44 +195,47 @@ exports[`ProjectSearch found search resu
             </div>
           </div>
         </SearchInput>
       </div>
       <ManagedTree
         autoExpandAll={true}
         autoExpandDepth={1}
         autoExpandNodeChildrenLimit={100}
+        focused={null}
         getChildren={[Function]}
         getParent={[Function]}
         getPath={[Function]}
         getRoots={[Function]}
         itemHeight={24}
         onFocus={[Function]}
         renderItem={[Function]}
       >
         <div
           className="managed-tree"
         >
           <Tree
             autoExpandAll={true}
             autoExpandDepth={1}
             autoExpandNodeChildrenLimit={100}
+            focused={null}
             getChildren={[Function]}
             getKey={[Function]}
             getParent={[Function]}
             getPath={[Function]}
             getRoots={[Function]}
             isExpanded={[Function]}
             itemHeight={24}
             onCollapse={[Function]}
             onExpand={[Function]}
             onFocus={[Function]}
             renderItem={[Function]}
           >
             <div
+              aria-activedescendant={null}
               className="tree "
               onBlur={[Function]}
               onFocus={[Function]}
               onKeyDown={[Function]}
               onKeyPress={[Function]}
               onKeyUp={[Function]}
               role="tree"
               style={Object {}}
@@ -832,16 +835,17 @@ exports[`ProjectSearch showErrorEmoji fa
         size="big"
         summaryMsg="5 results"
       />
     </div>
     <ManagedTree
       autoExpandAll={true}
       autoExpandDepth={1}
       autoExpandNodeChildrenLimit={100}
+      focused={null}
       getChildren={[Function]}
       getParent={[Function]}
       getPath={[Function]}
       getRoots={[Function]}
       itemHeight={24}
       onFocus={[Function]}
       renderItem={[Function]}
     />
--- a/devtools/client/debugger/new/src/components/test/__snapshots__/WelcomeBox.spec.js.snap
+++ b/devtools/client/debugger/new/src/components/test/__snapshots__/WelcomeBox.spec.js.snap
@@ -57,17 +57,17 @@ exports[`WelomeBox renders with default 
         </span>
         <span
           className="shortcutLabel"
         >
           Show all shortcuts
         </span>
       </p>
     </div>
-    <PaneToggleButton
-      collapsed={true}
-      handleClick={[MockFunction]}
-      horizontal={false}
-      position="end"
-    />
   </div>
+  <PaneToggleButton
+    collapsed={false}
+    handleClick={[MockFunction]}
+    horizontal={false}
+    position="end"
+  />
 </div>
 `;
--- a/devtools/client/debugger/new/src/components/variables.css
+++ b/devtools/client/debugger/new/src/components/variables.css
@@ -1,12 +1,21 @@
 /* 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/>. */
 
+: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 + 2px for its top and bottom borders */
+  --editor-searchbar-height: 26px;
+}
+
 :root.theme-light,
 :root .theme-light {
   --search-overlays-semitransparent: rgba(221, 225, 228, 0.66);
   --popup-shadow-color: #d0d0d0;
 }
 
 :root.theme-dark,
 :root .theme-dark {
--- a/devtools/client/debugger/new/src/reducers/async-requests.js
+++ b/devtools/client/debugger/new/src/reducers/async-requests.js
@@ -1,30 +1,32 @@
 /* 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
+
 /**
  * Async request reducer
  * @module reducers/async-request
  */
 
 const initialAsyncRequestState = [];
 
-function update(state = initialAsyncRequestState, action) {
+function update(state: string[] = initialAsyncRequestState, action: any) {
   const { seqId } = action;
 
   if (action.type === "NAVIGATE") {
     return initialAsyncRequestState;
   } else if (seqId) {
     let newState;
     if (action.status === "start") {
       newState = [...state, seqId];
     } else if (action.status === "error" || action.status === "done") {
-      newState = state.filter(id => id !== seqId);
+      newState = (state.filter(id => id !== seqId): string[]);
     }
 
     return newState;
   }
 
   return state;
 }
 
--- a/devtools/client/debugger/new/src/reducers/index.js
+++ b/devtools/client/debugger/new/src/reducers/index.js
@@ -1,12 +1,14 @@
 /* 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
+
 /**
  * Reducer index
  * @module reducers/index
  */
 
 import expressions from "./expressions";
 import sources from "./sources";
 import tabs from "./tabs";
--- a/devtools/client/debugger/new/src/reducers/quick-open.js
+++ b/devtools/client/debugger/new/src/reducers/quick-open.js
@@ -1,31 +1,33 @@
 /* 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
+
 /**
  * Quick Open reducer
  * @module reducers/quick-open
  */
 
 import makeRecord from "../utils/makeRecord";
 import { parseQuickOpenQuery } from "../utils/quick-open";
 import type { Action } from "../actions/types";
 import type { Record } from "../utils/makeRecord";
 
 export type QuickOpenType = "sources" | "functions" | "goto" | "gotoSource";
 
-type QuickOpenState = {
+export type QuickOpenState = {
   enabled: boolean,
   query: string,
   searchType: QuickOpenType
 };
 
-export const createQuickOpenState = makeRecord({
+export const createQuickOpenState: () => Record<QuickOpenState> = makeRecord({
   enabled: false,
   query: "",
   searchType: "sources"
 });
 
 export default function update(
   state: Record<QuickOpenState> = createQuickOpenState(),
   action: Action
--- a/devtools/client/debugger/new/src/reducers/tests/quick-open.spec.js
+++ b/devtools/client/debugger/new/src/reducers/tests/quick-open.spec.js
@@ -16,17 +16,17 @@ import update, {
 import {
   setQuickOpenQuery,
   openQuickOpen,
   closeQuickOpen
 } from "../../actions/quick-open";
 
 describe("quickOpen reducer", () => {
   test("initial state", () => {
-    const state = update(undefined, { type: "FAKE" });
+    const state = update(undefined, ({ type: "FAKE" }: any));
     expect(getQuickOpenQuery({ quickOpen: state })).toEqual("");
     expect(getQuickOpenType({ quickOpen: state })).toEqual("sources");
   });
 
   test("opens the quickOpen modal", () => {
     const state = update(createQuickOpenState(), openQuickOpen());
     expect(getQuickOpenEnabled({ quickOpen: state })).toEqual(true);
   });
--- a/devtools/client/debugger/new/src/reducers/types.js
+++ b/devtools/client/debugger/new/src/reducers/types.js
@@ -16,29 +16,31 @@ import type { DebuggeeState } from "./de
 import type { FileSearchState } from "./file-search";
 import type { PauseState } from "./pause";
 import type { PendingBreakpointsState } from "../selectors";
 import type { ProjectTextSearchState } from "./project-text-search";
 import type { Record } from "../utils/makeRecord";
 import type { SourcesState } from "./sources";
 import type { TabList } from "./tabs";
 import type { UIState } from "./ui";
+import type { QuickOpenState } from "./quick-open";
 
 export type State = {
   ast: Record<ASTState>,
   breakpoints: BreakpointsState,
   expressions: Record<ExpressionState>,
   debuggee: DebuggeeState,
   fileSearch: Record<FileSearchState>,
   pause: PauseState,
   pendingBreakpoints: PendingBreakpointsState,
   projectTextSearch: ProjectTextSearchState,
   sources: SourcesState,
   tabs: TabList,
-  ui: Record<UIState>
+  ui: Record<UIState>,
+  quickOpen: Record<QuickOpenState>
 };
 
 export type Selector<T> = State => T;
 
 export type PendingSelectedLocation = {
   url: string,
   line?: number,
   column?: number
--- a/devtools/client/debugger/new/src/selectors/breakpointAtLocation.js
+++ b/devtools/client/debugger/new/src/selectors/breakpointAtLocation.js
@@ -1,46 +1,50 @@
 /* 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 { getSelectedSource } from "../reducers/sources";
 import { getBreakpointsList } from "../reducers/breakpoints";
 import { isGenerated } from "../utils/source";
 
+import type { Breakpoint } from "../types";
+import type { State } from "../reducers/types";
+
 function getColumn(column, selectedSource) {
   if (column) {
     return column;
   }
 
   return isGenerated(selectedSource) ? undefined : 0;
 }
 
 function getLocation(bp, selectedSource) {
   return isGenerated(selectedSource)
     ? bp.generatedLocation || bp.location
     : bp.location;
 }
 
-function getBreakpointsForSource(
-  state: OuterState,
-  selectedSource: Source
-): Breakpoint[] {
+function getBreakpointsForSource(state: State, selectedSource): Breakpoint[] {
   const breakpoints = getBreakpointsList(state);
 
   return breakpoints.filter(bp => {
     const location = getLocation(bp, selectedSource);
     return location.sourceId === selectedSource.id;
   });
 }
 
+type LineColumn = { line: number, column: ?number };
+
 function findBreakpointAtLocation(
   breakpoints,
   selectedSource,
-  { line, column }
+  { line, column }: LineColumn
 ) {
   return breakpoints.find(breakpoint => {
     const location = getLocation(breakpoint, selectedSource);
     const sameLine = location.line === line;
     if (!sameLine) {
       return false;
     }
 
@@ -54,23 +58,29 @@ function findBreakpointAtLocation(
 
 /*
  * Finds a breakpoint at a location (line, column) of the
  * selected source.
  *
  * This is useful for finding a breakpoint when the
  * user clicks in the gutter or on a token.
  */
-export function getBreakpointAtLocation(state, location) {
+export function getBreakpointAtLocation(state: State, location: LineColumn) {
   const selectedSource = getSelectedSource(state);
+  if (!selectedSource) {
+    throw new Error("no selectedSource");
+  }
   const breakpoints = getBreakpointsForSource(state, selectedSource);
 
   return findBreakpointAtLocation(breakpoints, selectedSource, location);
 }
 
-export function getBreakpointsAtLine(state: OuterState, line: number) {
+export function getBreakpointsAtLine(state: State, line: number): Breakpoint[] {
   const selectedSource = getSelectedSource(state);
+  if (!selectedSource) {
+    throw new Error("no selectedSource");
+  }
   const breakpoints = getBreakpointsForSource(state, selectedSource);
 
   return breakpoints.filter(
     breakpoint => getLocation(breakpoint, selectedSource).line === line
   );
 }
--- a/devtools/client/debugger/new/src/selectors/getCallStackFrames.js
+++ b/devtools/client/debugger/new/src/selectors/getCallStackFrames.js
@@ -1,37 +1,48 @@
 /* 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 {
   getSources,
   getSelectedSource,
   getSourceInSources
 } from "../reducers/sources";
 import { getFrames } from "../reducers/pause";
 import { annotateFrames } from "../utils/pause/frames";
 import { isOriginal } from "../utils/source";
 import { get } from "lodash";
+import type { State } from "../reducers/types";
 import type { Frame, Source } from "../types";
 import type { SourcesMap } from "../reducers/sources";
 import { createSelector } from "reselect";
 
 function getLocation(frame, isGeneratedSource) {
   return isGeneratedSource
     ? frame.generatedLocation || frame.location
     : frame.location;
 }
 
-function getSourceForFrame(sources, frame, isGeneratedSource) {
+function getSourceForFrame(
+  sources: SourcesMap,
+  frame: Frame,
+  isGeneratedSource
+) {
   const sourceId = getLocation(frame, isGeneratedSource).sourceId;
   return getSourceInSources(sources, sourceId);
 }
 
-function appendSource(sources, frame, selectedSource) {
+function appendSource(
+  sources: SourcesMap,
+  frame: Frame,
+  selectedSource: ?Source
+): Frame {
   const isGeneratedSource = selectedSource && !isOriginal(selectedSource);
   return {
     ...frame,
     location: getLocation(frame, isGeneratedSource),
     source: getSourceForFrame(sources, frame, isGeneratedSource)
   };
 }
 
@@ -39,22 +50,22 @@ export function formatCallStackFrames(
   frames: Frame[],
   sources: SourcesMap,
   selectedSource: Source
 ) {
   if (!frames) {
     return null;
   }
 
-  const formattedFrames = frames
+  const formattedFrames: Frame[] = frames
     .filter(frame => getSourceForFrame(sources, frame))
     .map(frame => appendSource(sources, frame, selectedSource))
     .filter(frame => !get(frame, "source.isBlackBoxed"));
 
   return annotateFrames(formattedFrames);
 }
 
-export const getCallStackFrames = createSelector(
+export const getCallStackFrames: State => Frame[] = (createSelector: any)(
   getFrames,
   getSources,
   getSelectedSource,
   formatCallStackFrames
 );
--- a/devtools/client/debugger/new/src/selectors/isSelectedFrameVisible.js
+++ b/devtools/client/debugger/new/src/selectors/isSelectedFrameVisible.js
@@ -1,29 +1,32 @@
 /* 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 { originalToGeneratedId, isOriginalId } from "devtools-source-map";
 import { getSelectedFrame } from "../reducers/pause";
 import { getSelectedLocation } from "../reducers/sources";
+import type { State } from "../reducers/types";
 
 function getGeneratedId(sourceId) {
   if (isOriginalId(sourceId)) {
     return originalToGeneratedId(sourceId);
   }
 
   return sourceId;
 }
 
 /*
  * Checks to if the selected frame's source is currently
  * selected.
  */
-export function isSelectedFrameVisible(state) {
+export function isSelectedFrameVisible(state: State) {
   const selectedLocation = getSelectedLocation(state);
   const selectedFrame = getSelectedFrame(state);
 
   if (!selectedFrame || !selectedLocation) {
     return false;
   }
 
   if (isOriginalId(selectedLocation.sourceId)) {
--- a/devtools/client/debugger/new/src/selectors/visiblePausePoints.js
+++ b/devtools/client/debugger/new/src/selectors/visiblePausePoints.js
@@ -1,15 +1,19 @@
 /* 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 { getSelectedSource } from "../reducers/sources";
 import { getPausePoints } from "../reducers/ast";
 
-export function getVisiblePausePoints(state) {
+import type { State } from "../reducers/types";
+
+export function getVisiblePausePoints(state: State) {
   const source = getSelectedSource(state);
   if (!source) {
     return null;
   }
 
   return getPausePoints(state, source.id);
 }
--- a/devtools/client/debugger/new/src/test/__mocks__/request-animation-frame.js
+++ b/devtools/client/debugger/new/src/test/__mocks__/request-animation-frame.js
@@ -1,7 +1,10 @@
 /* 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
+
 global.requestAnimationFrame = function(cb) {
   cb();
   return null;
 };
--- a/devtools/client/debugger/new/src/test/__mocks__/styleMock.js
+++ b/devtools/client/debugger/new/src/test/__mocks__/styleMock.js
@@ -1,5 +1,7 @@
 /* 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
+
 module.exports = {};
--- a/devtools/client/debugger/new/src/test/__mocks__/svgMock.js
+++ b/devtools/client/debugger/new/src/test/__mocks__/svgMock.js
@@ -1,5 +1,7 @@
 /* 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
+
 module.exports = "<svg></svg>";
--- a/devtools/client/debugger/new/src/test/shim.js
+++ b/devtools/client/debugger/new/src/test/shim.js
@@ -1,5 +1,7 @@
 /* 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
+
 global.requestAnimationFrame = callback => setTimeout(callback, 0);
--- a/devtools/client/debugger/new/src/test/tests-setup.js
+++ b/devtools/client/debugger/new/src/test/tests-setup.js
@@ -1,18 +1,22 @@
 /* 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
+
+// $FlowIgnore
 global.Worker = require("workerjs");
 
 import path from "path";
 // import getConfig from "../../bin/getConfig";
 import { readFileSync } from "fs";
 import Enzyme from "enzyme";
+// $FlowIgnore
 import Adapter from "enzyme-adapter-react-16";
 import { setupHelper } from "../utils/dbg";
 import { prefs } from "../utils/prefs";
 
 import { startSourceMapWorker, stopSourceMapWorker } from "devtools-source-map";
 
 import {
   start as startPrettyPrintWorker,
@@ -60,17 +64,18 @@ global.indexedDB = mockIndexeddDB();
 Enzyme.configure({ adapter: new Adapter() });
 
 function formatException(reason, p) {
   console && console.log("Unhandled Rejection at:", p, "reason:", reason);
 }
 
 beforeAll(() => {
   startSourceMapWorker(
-    path.join(rootPath, "node_modules/devtools-source-map/src/worker.js")
+    path.join(rootPath, "node_modules/devtools-source-map/src/worker.js"),
+    ""
   );
   startPrettyPrintWorker(
     path.join(rootPath, "src/workers/pretty-print/worker.js")
   );
   startParserWorker(path.join(rootPath, "src/workers/parser/worker.js"));
   startSearchWorker(path.join(rootPath, "src/workers/search/worker.js"));
   process.on("unhandledRejection", formatException);
 });
--- a/devtools/client/debugger/new/src/test/utils/history.js
+++ b/devtools/client/debugger/new/src/test/utils/history.js
@@ -1,14 +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
+
 let logs = [];
-export function getHistory(query: ?string = null) {
+export function getHistory(query: ?string = null): any {
   if (!query) {
     return logs;
   }
 
   return logs.filter(log => log.type === query);
 }
 
 export function clearHistory() {
--- a/devtools/client/debugger/new/src/types.js
+++ b/devtools/client/debugger/new/src/types.js
@@ -182,23 +182,24 @@ export type FrameId = string;
  * @static
  */
 export type Frame = {
   id: FrameId,
   thread: string,
   displayName: string,
   location: SourceLocation,
   generatedLocation: SourceLocation,
-  source?: Source,
+  source: ?Source,
   scope: Scope,
   // FIXME Define this type more clearly
   this: Object,
   framework?: string,
   isOriginal?: boolean,
-  originalDisplayName?: string
+  originalDisplayName?: string,
+  library?: string
 };
 
 export type ChromeFrame = {
   id: FrameId,
   displayName: string,
   scopeChain: any,
   generatedLocation: SourceLocation,
   location: ?SourceLocation
--- a/devtools/client/debugger/new/src/utils/bootstrap.js
+++ b/devtools/client/debugger/new/src/utils/bootstrap.js
@@ -17,16 +17,17 @@ import * as parser from "../workers/pars
 
 import configureStore from "../actions/utils/create-store";
 import reducers from "../reducers";
 import * as selectors from "../selectors";
 import App from "../components/App";
 import { asyncStore, prefs } from "./prefs";
 
 import type { Panel } from "../client/firefox/types";
+import typeof SourceMaps from "../../packages/devtools-source-map/src";
 
 function renderPanel(component, store) {
   const root = document.createElement("div");
   root.className = "launchpad-root theme-body";
   root.style.setProperty("flex", "1");
   const mount = document.querySelector("#mount");
   if (!mount) {
     return;
@@ -36,17 +37,17 @@ function renderPanel(component, store) {
   ReactDOM.render(
     React.createElement(Provider, { store }, React.createElement(component)),
     root
   );
 }
 
 export function bootstrapStore(
   client: any,
-  sourceMaps: Object,
+  sourceMaps: SourceMaps,
   panel: Panel,
   initialState: Object
 ) {
   const createStore = configureStore({
     log: prefs.logging || isTesting(),
     timing: isDevelopment(),
     makeThunkArgs: (args, state) => {
       return { ...args, client, sourceMaps, panel };
--- a/devtools/client/debugger/new/src/utils/editor/source-editor.js
+++ b/devtools/client/debugger/new/src/utils/editor/source-editor.js
@@ -1,19 +1,22 @@
 /* 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
+
 /**
  * CodeMirror source editor utils
  * @module utils/source-editor
  */
 
 const CodeMirror = require("codemirror");
 
+// $FlowIgnore
 require("codemirror/lib/codemirror.css");
 require("codemirror/mode/javascript/javascript");
 require("codemirror/mode/htmlmixed/htmlmixed");
 require("codemirror/mode/coffeescript/coffeescript");
 require("codemirror/mode/jsx/jsx");
 require("codemirror/mode/elm/elm");
 require("codemirror/mode/clojure/clojure");
 require("codemirror/mode/haxe/haxe");
--- a/devtools/client/debugger/new/src/utils/editor/token-events.js
+++ b/devtools/client/debugger/new/src/utils/editor/token-events.js
@@ -1,15 +1,17 @@
-import { getTokenLocation } from ".";
-import { isEqual } from "lodash";
-
 /* 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 { getTokenLocation } from ".";
+import { isEqual } from "lodash";
+
 function isInvalidTarget(target: HTMLElement) {
   if (!target || !target.innerText) {
     return true;
   }
 
   const tokenText = target.innerText.trim();
   const cursorPos = target.getBoundingClientRect();
 
@@ -45,17 +47,17 @@ function dispatch(codeMirror, eventName,
 function invalidLeaveTarget(target: ?HTMLElement) {
   if (!target || target.closest(".popover")) {
     return true;
   }
 
   return false;
 }
 
-export function onMouseOver(codeMirror) {
+export function onMouseOver(codeMirror: any) {
   let prevTokenPos = null;
 
   function onMouseLeave(event) {
     if (invalidLeaveTarget(event.relatedTarget)) {
       return addMouseLeave(event.target);
     }
 
     prevTokenPos = null;
@@ -64,17 +66,17 @@ export function onMouseOver(codeMirror) 
 
   function addMouseLeave(target) {
     target.addEventListener("mouseleave", onMouseLeave, {
       capture: true,
       once: true
     });
   }
 
-  return enterEvent => {
+  return (enterEvent: any) => {
     const { target } = enterEvent;
 
     if (isInvalidTarget(target)) {
       return;
     }
 
     const tokenPos = getTokenLocation(codeMirror, target);
 
--- a/devtools/client/debugger/new/src/utils/pause/frames/collapseFrames.js
+++ b/devtools/client/debugger/new/src/utils/pause/frames/collapseFrames.js
@@ -2,37 +2,37 @@
  * 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 { get, findIndex } from "lodash";
 
 // eslint-disable-next-line max-len
-import type { LocalFrame } from "../../../components/SecondaryPanes/Frames/types";
+import type { Frame } from "../../../types";
 import { getFrameUrl } from "./getFrameUrl";
 
 function collapseLastFrames(frames) {
   const index = findIndex(frames, frame =>
     getFrameUrl(frame).match(/webpack\/bootstrap/i)
   );
 
   if (index == -1) {
     return { newFrames: frames, lastGroup: [] };
   }
 
   const newFrames = frames.slice(0, index);
   const lastGroup = frames.slice(index);
   return { newFrames, lastGroup };
 }
 
-type FrameGroup = LocalFrame[];
-type GroupedFrames = Array<FrameGroup | LocalFrame>;
+type FrameGroup = Frame[];
+type GroupedFrames = Array<FrameGroup | Frame>;
 
-export function collapseFrames(frames: LocalFrame[]): GroupedFrames {
+export function collapseFrames(frames: Frame[]): GroupedFrames {
   // We collapse groups of one so that user frames
   // are not in a group of one
   function addGroupToList(group, list) {
     if (!group) {
       return list;
     }
 
     if (group.length > 1) {
--- a/devtools/client/debugger/new/src/utils/pause/frames/displayName.js
+++ b/devtools/client/debugger/new/src/utils/pause/frames/displayName.js
@@ -1,16 +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
 
 // eslint-disable-next-line max-len
-import type { LocalFrame } from "../../../components/SecondaryPanes/Frames/types";
+import type { Frame } from "../../../types";
 import { getFilename } from "../../source";
 
 // Decodes an anonymous naming scheme that
 // spider monkey implements based on "Naming Anonymous JavaScript Functions"
 // http://johnjbarton.github.io/nonymous/index.html
 const objectProperty = /([\w\d\$]+)$/;
 const arrayProperty = /\[(.*?)\]$/;
 const functionProperty = /([\w\d]+)[\/\.<]*?$/;
@@ -68,37 +68,45 @@ const displayNameMap = {
 function mapDisplayNames(frame, library) {
   const { displayName } = frame;
   return (
     (displayNameMap[library] && displayNameMap[library][displayName]) ||
     displayName
   );
 }
 
-function getFrameDisplayName(frame: LocalFrame): string {
-  const { displayName, originalDisplayName, userDisplayName, name } = frame;
+function getFrameDisplayName(frame: Frame): string {
+  const {
+    displayName,
+    originalDisplayName,
+    userDisplayName,
+    name
+  } = (frame: any);
   return originalDisplayName || userDisplayName || displayName || name;
 }
 
 type formatDisplayNameParams = {
   shouldMapDisplayName: boolean
 };
 export function formatDisplayName(
-  frame: LocalFrame,
+  frame: Frame,
   { shouldMapDisplayName = true }: formatDisplayNameParams = {},
   l10n: typeof L10N
 ): string {
   const { library } = frame;
   let displayName = getFrameDisplayName(frame);
   if (library && shouldMapDisplayName) {
     displayName = mapDisplayNames(frame, library);
   }
 
   return simplifyDisplayName(displayName) || l10n.getStr("anonymousFunction");
 }
 
-export function formatCopyName(frame: LocalFrame, l10n: typeof L10N): string {
+export function formatCopyName(frame: Frame, l10n: typeof L10N): string {
   const displayName = formatDisplayName(frame, undefined, l10n);
+  if (!frame.source) {
+    throw new Error("no frame source");
+  }
   const fileName = getFilename(frame.source);
   const frameLocation = frame.location.line;
 
   return `${displayName} (${fileName}#${frameLocation})`;
 }
--- a/devtools/client/debugger/new/src/utils/pause/frames/tests/displayName.spec.js
+++ b/devtools/client/debugger/new/src/utils/pause/frames/tests/displayName.spec.js
@@ -5,97 +5,89 @@
 // @flow
 
 import {
   formatCopyName,
   formatDisplayName,
   simplifyDisplayName
 } from "../displayName";
 
+import { makeMockFrame, makeMockSource } from "../../../test-mockup";
+
 describe("formatCopyName", () => {
   it("simple", () => {
-    const frame = {
-      displayName: "child",
-      location: {
-        line: 12
-      },
-      source: {
-        url: "todo-view.js"
-      }
-    };
+    const source = makeMockSource("todo-view.js");
+    const frame = makeMockFrame(undefined, source, undefined, 12, "child");
 
     expect(formatCopyName(frame, L10N)).toEqual("child (todo-view.js#12)");
   });
 });
 
 describe("formatting display names", () => {
   it("uses a library description", () => {
+    const source = makeMockSource("assets/backbone.js");
     const frame = {
-      library: "Backbone",
-      displayName: "extend/child",
-      source: {
-        url: "assets/backbone.js"
-      }
+      ...makeMockFrame(undefined, source, undefined, undefined, "extend/child"),
+      library: "Backbone"
     };
 
     expect(formatDisplayName(frame, undefined, L10N)).toEqual("Create Class");
   });
 
   it("shortens an anonymous function", () => {
-    const frame = {
-      displayName: "extend/child/bar/baz",
-      source: {
-        url: "assets/bar.js"
-      }
-    };
+    const source = makeMockSource("assets/bar.js");
+    const frame = makeMockFrame(
+      undefined,
+      source,
+      undefined,
+      undefined,
+      "extend/child/bar/baz"
+    );
 
     expect(formatDisplayName(frame, undefined, L10N)).toEqual("baz");
   });
 
   it("does not truncates long function names", () => {
-    const frame = {
-      displayName: "bazbazbazbazbazbazbazbazbazbazbazbazbaz",
-      source: {
-        url: "assets/bar.js"
-      }
-    };
+    const source = makeMockSource("extend/child/bar/baz");
+    const frame = makeMockFrame(
+      undefined,
+      source,
+      undefined,
+      undefined,
+      "bazbazbazbazbazbazbazbazbazbazbazbazbaz"
+    );
 
     expect(formatDisplayName(frame, undefined, L10N)).toEqual(
       "bazbazbazbazbazbazbazbazbazbazbazbazbaz"
     );
   });
 
   it("returns the original function name when present", () => {
+    const source = makeMockSource("entry.js");
     const frame = {
+      ...makeMockFrame(undefined, source),
       originalDisplayName: "originalFn",
-      displayName: "fn",
-      source: {
-        url: "entry.js"
-      }
+      displayName: "fn"
     };
 
     expect(formatDisplayName(frame, undefined, L10N)).toEqual("originalFn");
   });
 
   it("returns anonymous when displayName is undefined", () => {
-    const frame = {};
+    const frame = { ...makeMockFrame(), displayName: undefined };
     expect(formatDisplayName(frame, undefined, L10N)).toEqual("<anonymous>");
   });
 
   it("returns anonymous when displayName is null", () => {
-    const frame = {
-      displayName: null
-    };
+    const frame = { ...makeMockFrame(), displayName: (null: any) };
     expect(formatDisplayName(frame, undefined, L10N)).toEqual("<anonymous>");
   });
 
   it("returns anonymous when displayName is an empty string", () => {
-    const frame = {
-      displayName: ""
-    };
+    const frame = { ...makeMockFrame(), displayName: "" };
     expect(formatDisplayName(frame, undefined, L10N)).toEqual("<anonymous>");
   });
 });
 
 describe("simplifying display names", () => {
   const cases = {
     defaultCase: [["define", "define"]],
 
--- a/devtools/client/debugger/new/src/utils/sources-tree/sortTree.js
+++ b/devtools/client/debugger/new/src/utils/sources-tree/sortTree.js
@@ -1,38 +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 { nodeHasChildren, isExactUrlMatch } from "./utils";
 
+import type { TreeDirectory } from "./types";
+
 /**
  * Look at the nodes in the source tree, and determine the index of where to
  * insert a new node. The ordering is index -> folder -> file.
  * @memberof utils/sources-tree
  * @static
  */
-export function sortEntireTree(tree, debuggeeUrl = "") {
+export function sortEntireTree(
+  tree: TreeDirectory,
+  debuggeeUrl: string = ""
+): TreeDirectory {
   if (nodeHasChildren(tree)) {
-    const contents = sortTree(tree, debuggeeUrl).map(subtree =>
+    const contents = sortTree(tree, debuggeeUrl).map((subtree: any) =>
       sortEntireTree(subtree)
     );
     return { ...tree, contents };
   }
   return tree;
 }
 
 /**
  * Look at the nodes in the source tree, and determine the index of where to
  * insert a new node. The ordering is index -> folder -> file.
  * @memberof utils/sources-tree
  * @static
  */
-export function sortTree(tree, debuggeeUrl = "") {
-  return tree.contents.sort((previousNode, currentNode) => {
+export function sortTree(tree: TreeDirectory, debuggeeUrl: string = "") {
+  return (tree.contents: any).sort((previousNode, currentNode) => {
     const currentNodeIsDir = nodeHasChildren(currentNode);
     const previousNodeIsDir = nodeHasChildren(previousNode);
     if (currentNode.name === "(index)") {
       return 1;
     } else if (previousNode.name === "(index)") {
       return -1;
     } else if (isExactUrlMatch(currentNode.name, debuggeeUrl)) {
       return 1;
--- a/devtools/client/debugger/new/src/utils/tabs.js
+++ b/devtools/client/debugger/new/src/utils/tabs.js
@@ -1,16 +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 type { Source } from "../types";
-import type { TabList } from "../reducers";
+import type { TabList } from "../reducers/tabs";
 
 type SourcesList = Source[];
 /*
  * Finds the hidden tabs by comparing the tabs' top offset.
  * hidden tabs will have a great top offset.
  *
  * @param sourceTabs Immutable.list
  * @param sourceTabEls HTMLCollection
@@ -36,17 +36,17 @@ export function getHiddenTabs(
   }
 
   return sourceTabs.filter((tab, index) => {
     const element = sourceTabEls[index];
     return element && hasTopOffset(element);
   });
 }
 
-export function getFramework(tabs: TabList[], url: string) {
+export function getFramework(tabs: TabList, url: string) {
   const tab = tabs.find(t => t.url === url);
 
   if (tab) {
     return tab.framework;
   }
 
   return "";
 }
--- a/devtools/client/debugger/new/src/utils/task.js
+++ b/devtools/client/debugger/new/src/utils/task.js
@@ -1,31 +1,33 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80 filetype=javascript: */
 /* 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
+
 /**
  * This object provides the public module functions.
  */
 export const Task = {
   // XXX: Not sure if this works in all cases...
-  async: function(task) {
+  async: function(task: any) {
     return function() {
       return Task.spawn(task, this, arguments);
     };
   },
 
   /**
    * Creates and starts a new task.
    * @param task A generator function
    * @return A promise, resolved when the task terminates
    */
-  spawn: function(task, scope, args) {
+  spawn: function(task: any, scope: any, args: any): Promise<any> {
     return new Promise(function(resolve, reject) {
       const iterator = task.apply(scope, args);
 
       const callNext = lastValue => {
         const iteration = iterator.next(lastValue);
         Promise.resolve(iteration.value)
           .then(value => {
             if (iteration.done) {
--- a/devtools/client/debugger/new/src/utils/test-mockup.js
+++ b/devtools/client/debugger/new/src/utils/test-mockup.js
@@ -103,23 +103,25 @@ function makeMockBreakpoint(
     originalText: "text",
     options: {}
   };
 }
 
 function makeMockFrame(
   id: FrameId = "frame",
   source: Source = makeMockSource("url"),
-  scope: Scope = makeMockScope()
+  scope: Scope = makeMockScope(),
+  line: number = 4,
+  displayName: string = `display-${id}`
 ): Frame {
-  const location = { sourceId: source.id, line: 4 };
+  const location = { sourceId: source.id, line };
   return {
     id,
     thread: "FakeThread",
-    displayName: `display-${id}`,
+    displayName,
     location,
     generatedLocation: location,
     source,
     scope,
     this: {}
   };
 }
 
--- a/devtools/client/debugger/new/src/utils/url.js
+++ b/devtools/client/debugger/new/src/utils/url.js
@@ -1,12 +1,14 @@
 /* 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 { memoize } from "lodash";
 
 const defaultUrl = {
   hash: "",
   host: "",
   hostname: "",
   href: "",
   origin: "null",
@@ -16,20 +18,20 @@ const defaultUrl = {
   port: "",
   protocol: "",
   search: "",
   // This should be a "URLSearchParams" object
   searchParams: {},
   username: ""
 };
 
-export const parse = memoize(function parse(url: string) {
+export const parse = memoize(function parse(url: string): any {
   try {
     const urlObj = new URL(url);
-    urlObj.path = urlObj.pathname + urlObj.search;
+    (urlObj: any).path = urlObj.pathname + urlObj.search;
     return urlObj;
   } catch (err) {
     // If we're given simply a filename...
     if (url) {
       return { ...defaultUrl, path: url, pathname: url };
     }
 
     return defaultUrl;
--- a/devtools/client/debugger/new/src/utils/worker.js
+++ b/devtools/client/debugger/new/src/utils/worker.js
@@ -1,27 +1,29 @@
 /* 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
+
 export type Message = {
   data: {
     id: string,
     method: string,
     args: Array<any>
   }
 };
 
 let msgId = 1;
 /**
  * @memberof utils/utils
  * @static
  */
 function workerTask(worker: any, method: string) {
-  return function(...args: any) {
+  return function(...args: any): Promise<any> {
     return new Promise((resolve, reject) => {
       const id = msgId++;
       worker.postMessage({ id, method, args });
 
       const listener = ({ data: result }) => {
         if (result.id !== id) {
           return;
         }
@@ -34,17 +36,17 @@ function workerTask(worker: any, method:
         }
       };
 
       worker.addEventListener("message", listener);
     });
   };
 }
 
-function workerHandler(publicInterface) {
+function workerHandler(publicInterface: any) {
   return function onTask(msg: Message) {
     const { id, method, args } = msg.data;
     const response = publicInterface[method].apply(null, args);
 
     if (response instanceof Promise) {
       response
         .then(val => self.postMessage({ id, response: val }))
         .catch(error => self.postMessage({ id, error }));
--- a/devtools/client/debugger/new/src/vendors.js
+++ b/devtools/client/debugger/new/src/vendors.js
@@ -1,26 +1,29 @@
 /* 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
+
 /**
  * Vendors.js is a file used to bundle and expose all dependencies needed to run
  * the transpiled debugger modules when running in Firefox.
  *
  * To make transpilation easier, a vendored module should always be imported in
  * same way:
  * - always with destructuring (import { a } from "modA";)
  * - always without destructuring (import modB from "modB")
  *
  * Both are fine, but cannot be mixed for the same module.
  */
 
 // Modules imported with destructuring
 import * as devtoolsComponents from "devtools-components";
+// $FlowIgnore
 import * as devtoolsConfig from "devtools-config";
 import * as devtoolsContextmenu from "devtools-contextmenu";
 import * as devtoolsEnvironment from "devtools-environment";
 import * as devtoolsModules from "devtools-modules";
 import * as devtoolsUtils from "devtools-utils";
 import * as fuzzaldrinPlus from "fuzzaldrin-plus";
 import * as transition from "react-transition-group/Transition";
 import * as reactAriaComponentsTabs from "react-aria-components/src/tabs";
--- a/devtools/client/debugger/new/src/workers/parser/mapBindings.js
+++ b/devtools/client/debugger/new/src/workers/parser/mapBindings.js
@@ -55,17 +55,17 @@ function getAssignmentTarget(node, bindi
 // translates new bindings `var a = 3` into `self.a = 3`
 // and existing bindings `var a = 3` into `a = 3` for re-assignments
 function globalizeDeclaration(node, bindings) {
   return node.declarations.map(declaration =>
     t.expressionStatement(
       t.assignmentExpression(
         "=",
         getAssignmentTarget(declaration.id, bindings),
-        declaration.init
+        declaration.init || t.unaryExpression("void", t.numericLiteral(0))
       )
     )
   );
 }
 
 // translates new bindings `a = 3` into `self.a = 3`
 // and keeps assignments the same for existing bindings.
 function globalizeAssignment(node, bindings) {
--- a/devtools/client/debugger/new/src/workers/parser/tests/helpers/index.js
+++ b/devtools/client/debugger/new/src/workers/parser/tests/helpers/index.js
@@ -1,38 +1,38 @@
 /* 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 fs from "fs";
 import path from "path";
 
-export function getFixture(name, type = "js") {
+import { makeMockSource } from "../../../../utils/test-mockup";
+
+export function getFixture(name: string, type: string = "js") {
   return fs.readFileSync(
     path.join(__dirname, `../fixtures/${name}.${type}`),
     "utf8"
   );
 }
 
-export function getSource(name, type) {
+export function getSource(name: string, type: string = "js") {
   const text = getFixture(name, type);
   let contentType = "text/javascript";
   if (type === "html") {
     contentType = "text/html";
   } else if (type === "vue") {
     contentType = "text/vue";
   } else if (type === "ts") {
     contentType = "text/typescript";
   } else if (type === "tsx") {
     contentType = "text/typescript-jsx";
   }
 
-  return {
-    id: name,
-    text,
-    contentType
-  };
+  return makeMockSource(undefined, name, contentType, text);
 }
 
-export function getOriginalSource(name, type) {
+export function getOriginalSource(name: string, type: string = "js") {
   const source = getSource(name, type);
   return { ...source, id: `${name}/originalSource-1` };
 }
--- a/devtools/client/debugger/new/src/workers/parser/tests/mapBindings.spec.js
+++ b/devtools/client/debugger/new/src/workers/parser/tests/mapBindings.spec.js
@@ -40,16 +40,26 @@ describe("mapExpressionBindings", () => 
       newExpression: "self.a = 2; self.b = 3; self.c = 4;"
     },
     {
       name: "multiple declarations",
       expression: "const a = 2, b = 3",
       newExpression: "self.a = 2; self.b = 3"
     },
     {
+      name: "declaration with separate assignment",
+      expression: "let a; a = 2;",
+      newExpression: "self.a = void 0; self.a = 2;"
+    },
+    {
+      name: "multiple declarations with no assignment",
+      expression: "let a = 2, b;",
+      newExpression: "self.a = 2; self.b = void 0;"
+    },
+    {
       name: "local bindings become assignments",
       bindings: ["a"],
       expression: "var a = 2;",
       newExpression: "a = 2;"
     },
     {
       name: "assignments",
       expression: "a = 2;",
--- a/devtools/client/debugger/new/src/workers/parser/tests/mapExpression.spec.js
+++ b/devtools/client/debugger/new/src/workers/parser/tests/mapExpression.spec.js
@@ -500,16 +500,34 @@ describe("mapExpression", () => {
       shouldMapBindings: false,
       expectedMapped: {
         await: true,
         bindings: false,
         originalExpression: false
       }
     },
     {
+      name: "await (no bindings, dynamic import)",
+      expression: `
+        var {rainbowLog} = await import("./cool-module.js");
+        rainbowLog("dynamic");`,
+      newExpression: `var rainbowLog;
+
+        (async () => {
+          ({rainbowLog} = await import("./cool-module.js"));
+          return rainbowLog("dynamic");
+        })()`,
+      shouldMapBindings: false,
+      expectedMapped: {
+        await: true,
+        bindings: false,
+        originalExpression: false
+      }
+    },
+    {
       name: "simple",
       expression: "a",
       newExpression: "a",
       bindings: [],
       mappings: {},
       shouldMapBindings: true,
       expectedMapped: {
         await: false,
--- a/devtools/client/debugger/new/src/workers/parser/tests/pausePoints.spec.js
+++ b/devtools/client/debugger/new/src/workers/parser/tests/pausePoints.spec.js
@@ -22,17 +22,17 @@ cases(
       ? getOriginalSource(file, type)
       : getSource(file, type);
 
     setSource(source);
 
     // The coercion here is needed because getPausePoints and convertToList
     // operate on two incompatible definitions of PausePointsMap
     const nodes = convertToList((getPausePoints(source.id): any));
-    expect(formatPausePoints(source.text, nodes)).toMatchSnapshot();
+    expect(formatPausePoints(source.text || "", nodes)).toMatchSnapshot();
   },
   [
     { name: "control-flow", file: "control-flow" },
     { name: "flow", file: "flow", original: true },
     { name: "calls", file: "calls" },
     { name: "statements", file: "statements" },
     { name: "modules", file: "modules", original: true },
     { name: "jsx", file: "jsx", original: true },
--- a/devtools/client/debugger/new/src/workers/parser/utils/ast.js
+++ b/devtools/client/debugger/new/src/workers/parser/utils/ast.js
@@ -96,17 +96,17 @@ function parseVueScript(code) {
     ast = parse(code, sourceOptions.original);
   }
   return ast;
 }
 
 export function parseConsoleScript(text: string, opts?: Object): Object | null {
   try {
     return _parse(text, {
-      plugins: ["objectRestSpread"],
+      plugins: ["objectRestSpread", "dynamicImport"],
       ...opts,
       allowAwaitOutsideFunction: true
     });
   } catch (e) {
     return null;
   }
 }
 
--- a/devtools/client/debugger/new/src/workers/parser/utils/formatSymbols.js
+++ b/devtools/client/debugger/new/src/workers/parser/utils/formatSymbols.js
@@ -1,15 +1,19 @@
 /* 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 { getSymbols } from "../getSymbols";
 import { setSource } from "../sources";
 
+import type { Source } from "../../../types";
+
 function formatLocation(loc) {
   if (!loc) {
     return "";
   }
 
   const { start, end } = loc;
   const startLoc = `(${start.line}, ${start.column})`;
   const endLoc = `(${end.line}, ${end.column})`;
@@ -35,17 +39,17 @@ function summarize(symbol) {
 
   return `${loc} ${expression} ${name}${params} ${klass} ${names} ${values} ${index}`.trim(); // eslint-disable-line max-len
 }
 const bools = ["hasJsx", "hasTypes", "loading"];
 function formatBool(name, symbols) {
   return `${name}: ${symbols[name] ? "true" : "false"}`;
 }
 
-function formatKey(name, symbols) {
+function formatKey(name: string, symbols: any) {
   if (bools.includes(name)) {
     return formatBool(name, symbols);
   }
 
   return `${name}:\n${symbols[name].map(summarize).join("\n")}`;
 }
 
 export function formatSymbols(source: Source) {
--- a/devtools/client/debugger/new/src/workers/search/get-matches.js
+++ b/devtools/client/debugger/new/src/workers/search/get-matches.js
@@ -1,32 +1,41 @@
 /* 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 assert from "../../utils/assert";
 import buildQuery from "../../utils/build-query";
 
+import type { SearchModifiers } from "../../types";
+
 export default function getMatches(
   query: string,
   text: string,
   modifiers: SearchModifiers
-): number {
+): Object[] {
   if (!query || !text || !modifiers) {
     return [];
   }
   const regexQuery = buildQuery(query, modifiers, {
     isGlobal: true
   });
   const matchedLocations = [];
   const lines = text.split("\n");
   for (let i = 0; i < lines.length; i++) {
     let singleMatch;
     const line = lines[i];
     while ((singleMatch = regexQuery.exec(line)) !== null) {
+      // Flow doesn't understand the test above.
+      if (!singleMatch) {
+        throw new Error("no singleMatch");
+      }
+
       matchedLocations.push({ line: i, ch: singleMatch.index });
 
       // When the match is an empty string the regexQuery.lastIndex will not
       // change resulting in an infinite loop so we need to check for this and
       // increment it manually in that case.  See issue #7023
       if (singleMatch[0] === "") {
         assert(
           !regexQuery.unicode,
--- a/devtools/client/debugger/new/src/workers/search/index.js
+++ b/devtools/client/debugger/new/src/workers/search/index.js
@@ -1,12 +1,14 @@
 /* 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 { workerUtils } from "devtools-utils";
 const { WorkerDispatcher } = workerUtils;
 
 const dispatcher = new WorkerDispatcher();
 export const start = dispatcher.start.bind(dispatcher);
 export const stop = dispatcher.stop.bind(dispatcher);
 
 export const getMatches = dispatcher.task("getMatches");
--- a/devtools/client/debugger/new/src/workers/search/project-search.js
+++ b/devtools/client/debugger/new/src/workers/search/project-search.js
@@ -1,19 +1,23 @@
 /* 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
+
 // Maybe reuse file search's functions?
 
 import getMatches from "./get-matches";
 
-export function findSourceMatches(source, queryText) {
+import type { Source } from "../../types";
+
+export function findSourceMatches(source: Source, queryText: string): Object[] {
   const { id, loadedState, text } = source;
-  if (loadedState != "loaded" || !text || queryText == "") {
+  if (loadedState != "loaded" || typeof text != "string" || queryText == "") {
     return [];
   }
 
   const modifiers = {
     caseSensitive: false,
     regexMatch: false,
     wholeWord: false
   };
--- a/devtools/client/debugger/new/src/workers/search/tests/project-search.spec.js
+++ b/devtools/client/debugger/new/src/workers/search/tests/project-search.spec.js
@@ -12,44 +12,44 @@ const text = `
   }
 `;
 
 describe("project search", () => {
   const emptyResults = [];
 
   it("throws on lack of source", () => {
     const needle = "test";
-    const source = null;
+    const source: any = null;
     const matches = () => findSourceMatches(source, needle);
     expect(matches).toThrow(TypeError);
   });
 
   it("handles empty source object", () => {
     const needle = "test";
-    const source = {};
+    const source: any = {};
     const matches = findSourceMatches(source, needle);
     expect(matches).toEqual(emptyResults);
   });
 
   it("finds matches", () => {
     const needle = "foo";
-    const source = {
+    const source: any = {
       text,
       loadedState: "loaded",
       id: "bar.js",
       url: "http://example.com/foo/bar.js"
     };
 
     const matches = findSourceMatches(source, needle);
     expect(matches).toMatchSnapshot();
   });
 
   it("finds no matches in source", () => {
     const needle = "test";
-    const source = {
+    const source: any = {
       text,
       loadedState: "loaded",
       id: "bar.js",
       url: "http://example.com/foo/bar.js"
     };
     const matches = findSourceMatches(source, needle);
     expect(matches).toEqual(emptyResults);
   });
--- a/devtools/client/debugger/new/src/workers/search/worker.js
+++ b/devtools/client/debugger/new/src/workers/search/worker.js
@@ -1,10 +1,12 @@
 /* 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 getMatches from "./get-matches";
 import { findSourceMatches } from "./project-search";
 import { workerUtils } from "devtools-utils";
 const { workerHandler } = workerUtils;
 
 self.onmessage = workerHandler({ getMatches, findSourceMatches });
--- a/devtools/client/debugger/new/test/mochitest/browser.ini
+++ b/devtools/client/debugger/new/test/mochitest/browser.ini
@@ -695,16 +695,17 @@ skip-if = (verify && !debug && (os == 'l
 skip-if = (os == "win" && ccov) # Bug 1424154
 [browser_dbg-debugger-buttons.js]
 [browser_dbg-editor-gutter.js]
 [browser_dbg-editor-select.js]
 [browser_dbg-editor-highlight.js]
 [browser_dbg-ember-quickstart.js]
 [browser_dbg-expressions.js]
 [browser_dbg-expressions-error.js]
+[browser_dbg-expressions-focus.js]
 [browser_dbg-iframes.js]
 [browser_dbg-inline-cache.js]
 skip-if = ccov && os == 'win' # Bug 1443132
 [browser_dbg-inspector-integration.js]
 [browser_dbg-keyboard-navigation.js]
 [browser_dbg-keyboard-shortcuts.js]
 skip-if = os == "linux" # bug 1351952
 [browser_dbg-layout-changes.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-expressions-focus.js
@@ -0,0 +1,19 @@
+/* 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/>. */
+
+// Ensures the input is displayed and focused when "+" is clicked
+add_task(async function() {
+  const dbg = await initDebugger("doc-script-switching.html");
+  // Close the panel
+  clickElementWithSelector(dbg, ".watch-expressions-pane ._header");
+  // Click + to add the new expression
+  clickElementWithSelector(dbg, ".watch-expressions-pane ._header .plus");
+  // Ensure element gets focused
+  await waitForElementWithSelector(dbg, ".expression-input-container.focused");
+  // Ensure the element is focused
+  is(
+    dbg.win.document.activeElement.classList.contains("input-expression"),
+    true
+  );
+});
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-expressions.js
+++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-expressions.js
@@ -1,10 +1,11 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.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/>. */
 
 /**
  * tests the watch expressions component
  * 1. add watch expressions
  * 2. edit watch expressions
  * 3. delete watch expressions
  * 4. expanding properties when not paused
  */
--- a/devtools/client/shared/source-map/index.js
+++ b/devtools/client/shared/source-map/index.js
@@ -414,80 +414,103 @@ function isSlowBuffer (obj) {
 /***/ }),
 
 /***/ 3646:
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.stopSourceMapWorker = exports.startSourceMapWorker = exports.isOriginalId = exports.isGeneratedId = exports.generatedToOriginalId = exports.originalToGeneratedId = exports.getOriginalStackFrames = exports.hasMappedSource = exports.clearSourceMaps = exports.applySourceMap = exports.getOriginalSourceText = exports.getLocationScopes = exports.getFileGeneratedRange = exports.getOriginalLocation = exports.getAllGeneratedLocations = exports.getGeneratedLocation = exports.getGeneratedRanges = exports.getOriginalRanges = exports.hasOriginalURL = exports.getOriginalURLs = exports.setAssetRootURL = exports.dispatcher = undefined;
+
+var _utils = __webpack_require__(3652);
+
+Object.defineProperty(exports, "originalToGeneratedId", {
+  enumerable: true,
+  get: function () {
+    return _utils.originalToGeneratedId;
+  }
+});
+Object.defineProperty(exports, "generatedToOriginalId", {
+  enumerable: true,
+  get: function () {
+    return _utils.generatedToOriginalId;
+  }
+});
+Object.defineProperty(exports, "isGeneratedId", {
+  enumerable: true,
+  get: function () {
+    return _utils.isGeneratedId;
+  }
+});
+Object.defineProperty(exports, "isOriginalId", {
+  enumerable: true,
+  get: function () {
+    return _utils.isOriginalId;
+  }
+});
+
+var _devtoolsSourceMap = __webpack_require__(3646);
+
+var self = _interopRequireWildcard(_devtoolsSourceMap);
+
+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; } }
+
 /* 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 {
-  originalToGeneratedId,
-  generatedToOriginalId,
-  isGeneratedId,
-  isOriginalId
-} = __webpack_require__(3652);
-
-const {
   workerUtils: { WorkerDispatcher }
 } = __webpack_require__(3651);
 
-const dispatcher = new WorkerDispatcher();
+const dispatcher = exports.dispatcher = new WorkerDispatcher();
+
+const setAssetRootURL = exports.setAssetRootURL = async assetRoot => dispatcher.invoke("setAssetRootURL", assetRoot);
+
+const getOriginalURLs = exports.getOriginalURLs = async generatedSource => dispatcher.invoke("getOriginalURLs", generatedSource);
 
-const setAssetRootURL = dispatcher.task("setAssetRootURL");
-const getOriginalURLs = dispatcher.task("getOriginalURLs");
-const hasOriginalURL = dispatcher.task("hasOriginalURL");
-const getOriginalRanges = dispatcher.task("getOriginalRanges");
-const getGeneratedRanges = dispatcher.task("getGeneratedRanges", {
-  queue: true
-});
-const getGeneratedLocation = dispatcher.task("getGeneratedLocation", {
+const hasOriginalURL = exports.hasOriginalURL = async url => dispatcher.invoke("hasOriginalURL", url);
+
+const getOriginalRanges = exports.getOriginalRanges = async (sourceId, url) => dispatcher.invoke("getOriginalRanges", sourceId, url);
+
+const getGeneratedRanges = exports.getGeneratedRanges = async (location, originalSource) => dispatcher.task("getGeneratedRanges", {
   queue: true
-});
-const getAllGeneratedLocations = dispatcher.task("getAllGeneratedLocations", {
-  queue: true
-});
-const getOriginalLocation = dispatcher.task("getOriginalLocation");
-const getFileGeneratedRange = dispatcher.task("getFileGeneratedRange");
-const getLocationScopes = dispatcher.task("getLocationScopes");
-const getOriginalSourceText = dispatcher.task("getOriginalSourceText");
-const applySourceMap = dispatcher.task("applySourceMap");
-const clearSourceMaps = dispatcher.task("clearSourceMaps");
-const hasMappedSource = dispatcher.task("hasMappedSource");
-const getOriginalStackFrames = dispatcher.task("getOriginalStackFrames");
+})(location, originalSource);
+
+const getGeneratedLocation = exports.getGeneratedLocation = async (location, originalSource) => dispatcher.task("getGeneratedLocation", { queue: true })(location, originalSource);
+
+const getAllGeneratedLocations = exports.getAllGeneratedLocations = async (location, originalSource) => dispatcher.task("getAllGeneratedLocations", { queue: true })(location, originalSource);
+
+const getOriginalLocation = exports.getOriginalLocation = async (location, options = {}) => dispatcher.invoke("getOriginalLocation", location, options);
 
-module.exports = {
-  originalToGeneratedId,
-  generatedToOriginalId,
-  isGeneratedId,
-  isOriginalId,
-  hasMappedSource,
-  getOriginalURLs,
-  hasOriginalURL,
-  getOriginalRanges,
-  getGeneratedRanges,
-  getGeneratedLocation,
-  getAllGeneratedLocations,
-  getOriginalLocation,
-  getFileGeneratedRange,
-  getLocationScopes,
-  getOriginalSourceText,
-  applySourceMap,
-  clearSourceMaps,
-  getOriginalStackFrames,
-  startSourceMapWorker(url, assetRoot) {
-    dispatcher.start(url);
-    setAssetRootURL(assetRoot);
-  },
-  stopSourceMapWorker: dispatcher.stop.bind(dispatcher)
+const getFileGeneratedRange = exports.getFileGeneratedRange = async originalSource => dispatcher.invoke("getFileGeneratedRange", originalSource);
+
+const getLocationScopes = exports.getLocationScopes = dispatcher.task("getLocationScopes");
+
+const getOriginalSourceText = exports.getOriginalSourceText = async originalSource => dispatcher.invoke("getOriginalSourceText", originalSource);
+
+const applySourceMap = exports.applySourceMap = async (generatedId, url, code, mappings) => dispatcher.invoke("applySourceMap", generatedId, url, code, mappings);
+
+const clearSourceMaps = exports.clearSourceMaps = async () => dispatcher.invoke("clearSourceMaps");
+
+const hasMappedSource = exports.hasMappedSource = async location => dispatcher.invoke("hasMappedSource", location);
+
+const getOriginalStackFrames = exports.getOriginalStackFrames = async generatedLocation => dispatcher.invoke("getOriginalStackFrames", generatedLocation);
+
+const startSourceMapWorker = exports.startSourceMapWorker = (url, assetRoot) => {
+  dispatcher.start(url);
+  setAssetRootURL(assetRoot);
 };
+const stopSourceMapWorker = exports.stopSourceMapWorker = dispatcher.stop.bind(dispatcher);
+
+exports.default = self;
 
 /***/ }),
 
 /***/ 3651:
 /***/ (function(module, exports, __webpack_require__) {
 
 /* 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
--- a/devtools/client/shared/source-map/worker.js
+++ b/devtools/client/shared/source-map/worker.js
@@ -408,16 +408,556 @@ function isBuffer (obj) {
 // For Node v0.10 support. Remove this eventually.
 function isSlowBuffer (obj) {
   return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0))
 }
 
 
 /***/ }),
 
+/***/ 3641:
+/***/ (function(module, exports, __webpack_require__) {
+
+/* WEBPACK VAR INJECTION */(function(module, global) {var __WEBPACK_AMD_DEFINE_RESULT__;/*! https://mths.be/punycode v1.4.1 by @mathias */
+;(function(root) {
+
+	/** Detect free variables */
+	var freeExports = typeof exports == 'object' && exports &&
+		!exports.nodeType && exports;
+	var freeModule = typeof module == 'object' && module &&
+		!module.nodeType && module;
+	var freeGlobal = typeof global == 'object' && global;
+	if (
+		freeGlobal.global === freeGlobal ||
+		freeGlobal.window === freeGlobal ||
+		freeGlobal.self === freeGlobal
+	) {
+		root = freeGlobal;
+	}
+
+	/**
+	 * The `punycode` object.
+	 * @name punycode
+	 * @type Object
+	 */
+	var punycode,
+
+	/** Highest positive signed 32-bit float value */
+	maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
+
+	/** Bootstring parameters */
+	base = 36,
+	tMin = 1,
+	tMax = 26,
+	skew = 38,
+	damp = 700,
+	initialBias = 72,
+	initialN = 128, // 0x80
+	delimiter = '-', // '\x2D'
+
+	/** Regular expressions */
+	regexPunycode = /^xn--/,
+	regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
+	regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
+
+	/** Error messages */
+	errors = {
+		'overflow': 'Overflow: input needs wider integers to process',
+		'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
+		'invalid-input': 'Invalid input'
+	},
+
+	/** Convenience shortcuts */
+	baseMinusTMin = base - tMin,
+	floor = Math.floor,
+	stringFromCharCode = String.fromCharCode,
+
+	/** Temporary variable */
+	key;
+
+	/*--------------------------------------------------------------------------*/
+
+	/**
+	 * A generic error utility function.
+	 * @private
+	 * @param {String} type The error type.
+	 * @returns {Error} Throws a `RangeError` with the applicable error message.
+	 */
+	function error(type) {
+		throw new RangeError(errors[type]);
+	}
+
+	/**
+	 * A generic `Array#map` utility function.
+	 * @private
+	 * @param {Array} array The array to iterate over.
+	 * @param {Function} callback The function that gets called for every array
+	 * item.
+	 * @returns {Array} A new array of values returned by the callback function.
+	 */
+	function map(array, fn) {
+		var length = array.length;
+		var result = [];
+		while (length--) {
+			result[length] = fn(array[length]);
+		}
+		return result;
+	}
+
+	/**
+	 * A simple `Array#map`-like wrapper to work with domain name strings or email
+	 * addresses.
+	 * @private
+	 * @param {String} domain The domain name or email address.
+	 * @param {Function} callback The function that gets called for every
+	 * character.
+	 * @returns {Array} A new string of characters returned by the callback
+	 * function.
+	 */
+	function mapDomain(string, fn) {
+		var parts = string.split('@');
+		var result = '';
+		if (parts.length > 1) {
+			// In email addresses, only the domain name should be punycoded. Leave
+			// the local part (i.e. everything up to `@`) intact.
+			result = parts[0] + '@';
+			string = parts[1];
+		}
+		// Avoid `split(regex)` for IE8 compatibility. See #17.
+		string = string.replace(regexSeparators, '\x2E');
+		var labels = string.split('.');
+		var encoded = map(labels, fn).join('.');
+		return result + encoded;
+	}
+
+	/**
+	 * Creates an array containing the numeric code points of each Unicode
+	 * character in the string. While JavaScript uses UCS-2 internally,
+	 * this function will convert a pair of surrogate halves (each of which
+	 * UCS-2 exposes as separate characters) into a single code point,
+	 * matching UTF-16.
+	 * @see `punycode.ucs2.encode`
+	 * @see <https://mathiasbynens.be/notes/javascript-encoding>
+	 * @memberOf punycode.ucs2
+	 * @name decode
+	 * @param {String} string The Unicode input string (UCS-2).
+	 * @returns {Array} The new array of code points.
+	 */
+	function ucs2decode(string) {
+		var output = [],
+		    counter = 0,
+		    length = string.length,
+		    value,
+		    extra;
+		while (counter < length) {
+			value = string.charCodeAt(counter++);
+			if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
+				// high surrogate, and there is a next character
+				extra = string.charCodeAt(counter++);
+				if ((extra & 0xFC00) == 0xDC00) { // low surrogate
+					output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
+				} else {
+					// unmatched surrogate; only append this code unit, in case the next
+					// code unit is the high surrogate of a surrogate pair
+					output.push(value);
+					counter--;
+				}
+			} else {
+				output.push(value);
+			}
+		}
+		return output;
+	}
+
+	/**
+	 * Creates a string based on an array of numeric code points.
+	 * @see `punycode.ucs2.decode`
+	 * @memberOf punycode.ucs2
+	 * @name encode
+	 * @param {Array} codePoints The array of numeric code points.
+	 * @returns {String} The new Unicode string (UCS-2).
+	 */
+	function ucs2encode(array) {
+		return map(array, function(value) {
+			var output = '';
+			if (value > 0xFFFF) {
+				value -= 0x10000;
+				output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
+				value = 0xDC00 | value & 0x3FF;
+			}
+			output += stringFromCharCode(value);
+			return output;
+		}).join('');
+	}
+
+	/**
+	 * Converts a basic code point into a digit/integer.
+	 * @see `digitToBasic()`
+	 * @private
+	 * @param {Number} codePoint The basic numeric code point value.
+	 * @returns {Number} The numeric value of a basic code point (for use in
+	 * representing integers) in the range `0` to `base - 1`, or `base` if
+	 * the code point does not represent a value.
+	 */
+	function basicToDigit(codePoint) {
+		if (codePoint - 48 < 10) {
+			return codePoint - 22;
+		}
+		if (codePoint - 65 < 26) {
+			return codePoint - 65;
+		}
+		if (codePoint - 97 < 26) {
+			return codePoint - 97;
+		}
+		return base;
+	}
+
+	/**
+	 * Converts a digit/integer into a basic code point.
+	 * @see `basicToDigit()`
+	 * @private
+	 * @param {Number} digit The numeric value of a basic code point.
+	 * @returns {Number} The basic code point whose value (when used for
+	 * representing integers) is `digit`, which needs to be in the range
+	 * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
+	 * used; else, the lowercase form is used. The behavior is undefined
+	 * if `flag` is non-zero and `digit` has no uppercase form.
+	 */
+	function digitToBasic(digit, flag) {
+		//  0..25 map to ASCII a..z or A..Z
+		// 26..35 map to ASCII 0..9
+		return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
+	}
+
+	/**
+	 * Bias adaptation function as per section 3.4 of RFC 3492.
+	 * https://tools.ietf.org/html/rfc3492#section-3.4
+	 * @private
+	 */
+	function adapt(delta, numPoints, firstTime) {
+		var k = 0;
+		delta = firstTime ? floor(delta / damp) : delta >> 1;
+		delta += floor(delta / numPoints);
+		for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
+			delta = floor(delta / baseMinusTMin);
+		}
+		return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
+	}
+
+	/**
+	 * Converts a Punycode string of ASCII-only symbols to a string of Unicode
+	 * symbols.
+	 * @memberOf punycode
+	 * @param {String} input The Punycode string of ASCII-only symbols.
+	 * @returns {String} The resulting string of Unicode symbols.
+	 */
+	function decode(input) {
+		// Don't use UCS-2
+		var output = [],
+		    inputLength = input.length,
+		    out,
+		    i = 0,
+		    n = initialN,
+		    bias = initialBias,
+		    basic,
+		    j,
+		    index,
+		    oldi,
+		    w,
+		    k,
+		    digit,
+		    t,
+		    /** Cached calculation results */
+		    baseMinusT;
+
+		// Handle the basic code points: let `basic` be the number of input code
+		// points before the last delimiter, or `0` if there is none, then copy
+		// the first basic code points to the output.
+
+		basic = input.lastIndexOf(delimiter);
+		if (basic < 0) {
+			basic = 0;
+		}
+
+		for (j = 0; j < basic; ++j) {
+			// if it's not a basic code point
+			if (input.charCodeAt(j) >= 0x80) {
+				error('not-basic');
+			}
+			output.push(input.charCodeAt(j));
+		}
+
+		// Main decoding loop: start just after the last delimiter if any basic code
+		// points were copied; start at the beginning otherwise.
+
+		for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
+
+			// `index` is the index of the next character to be consumed.
+			// Decode a generalized variable-length integer into `delta`,
+			// which gets added to `i`. The overflow checking is easier
+			// if we increase `i` as we go, then subtract off its starting
+			// value at the end to obtain `delta`.
+			for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
+
+				if (index >= inputLength) {
+					error('invalid-input');
+				}
+
+				digit = basicToDigit(input.charCodeAt(index++));
+
+				if (digit >= base || digit > floor((maxInt - i) / w)) {
+					error('overflow');
+				}
+
+				i += digit * w;
+				t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+
+				if (digit < t) {
+					break;
+				}
+
+				baseMinusT = base - t;
+				if (w > floor(maxInt / baseMinusT)) {
+					error('overflow');
+				}
+
+				w *= baseMinusT;
+
+			}
+
+			out = output.length + 1;
+			bias = adapt(i - oldi, out, oldi == 0);
+
+			// `i` was supposed to wrap around from `out` to `0`,
+			// incrementing `n` each time, so we'll fix that now:
+			if (floor(i / out) > maxInt - n) {
+				error('overflow');
+			}
+
+			n += floor(i / out);
+			i %= out;
+
+			// Insert `n` at position `i` of the output
+			output.splice(i++, 0, n);
+
+		}
+
+		return ucs2encode(output);
+	}
+
+	/**
+	 * Converts a string of Unicode symbols (e.g. a domain name label) to a
+	 * Punycode string of ASCII-only symbols.
+	 * @memberOf punycode
+	 * @param {String} input The string of Unicode symbols.
+	 * @returns {String} The resulting Punycode string of ASCII-only symbols.
+	 */
+	function encode(input) {
+		var n,
+		    delta,
+		    handledCPCount,
+		    basicLength,
+		    bias,
+		    j,
+		    m,
+		    q,
+		    k,
+		    t,
+		    currentValue,
+		    output = [],
+		    /** `inputLength` will hold the number of code points in `input`. */
+		    inputLength,
+		    /** Cached calculation results */
+		    handledCPCountPlusOne,
+		    baseMinusT,
+		    qMinusT;
+
+		// Convert the input in UCS-2 to Unicode
+		input = ucs2decode(input);
+
+		// Cache the length
+		inputLength = input.length;
+
+		// Initialize the state
+		n = initialN;
+		delta = 0;
+		bias = initialBias;
+
+		// Handle the basic code points
+		for (j = 0; j < inputLength; ++j) {
+			currentValue = input[j];
+			if (currentValue < 0x80) {
+				output.push(stringFromCharCode(currentValue));
+			}
+		}
+
+		handledCPCount = basicLength = output.length;
+
+		// `handledCPCount` is the number of code points that have been handled;
+		// `basicLength` is the number of basic code points.
+
+		// Finish the basic string - if it is not empty - with a delimiter
+		if (basicLength) {
+			output.push(delimiter);
+		}
+
+		// Main encoding loop:
+		while (handledCPCount < inputLength) {
+
+			// All non-basic code points < n have been handled already. Find the next
+			// larger one:
+			for (m = maxInt, j = 0; j < inputLength; ++j) {
+				currentValue = input[j];
+				if (currentValue >= n && currentValue < m) {
+					m = currentValue;
+				}
+			}
+
+			// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
+			// but guard against overflow
+			handledCPCountPlusOne = handledCPCount + 1;
+			if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
+				error('overflow');
+			}
+
+			delta += (m - n) * handledCPCountPlusOne;
+			n = m;
+
+			for (j = 0; j < inputLength; ++j) {
+				currentValue = input[j];
+
+				if (currentValue < n && ++delta > maxInt) {
+					error('overflow');
+				}
+
+				if (currentValue == n) {
+					// Represent delta as a generalized variable-length integer
+					for (q = delta, k = base; /* no condition */; k += base) {
+						t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+						if (q < t) {
+							break;
+						}
+						qMinusT = q - t;
+						baseMinusT = base - t;
+						output.push(
+							stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
+						);
+						q = floor(qMinusT / baseMinusT);
+					}
+
+					output.push(stringFromCharCode(digitToBasic(q, 0)));
+					bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
+					delta = 0;
+					++handledCPCount;
+				}
+			}
+
+			++delta;
+			++n;
+
+		}
+		return output.join('');
+	}
+
+	/**
+	 * Converts a Punycode string representing a domain name or an email address
+	 * to Unicode. Only the Punycoded parts of the input will be converted, i.e.
+	 * it doesn't matter if you call it on a string that has already been
+	 * converted to Unicode.
+	 * @memberOf punycode
+	 * @param {String} input The Punycoded domain name or email address to
+	 * convert to Unicode.
+	 * @returns {String} The Unicode representation of the given Punycode
+	 * string.
+	 */
+	function toUnicode(input) {
+		return mapDomain(input, function(string) {
+			return regexPunycode.test(string)
+				? decode(string.slice(4).toLowerCase())
+				: string;
+		});
+	}
+
+	/**
+	 * Converts a Unicode string representing a domain name or an email address to
+	 * Punycode. Only the non-ASCII parts of the domain name will be converted,
+	 * i.e. it doesn't matter if you call it with a domain that's already in
+	 * ASCII.
+	 * @memberOf punycode
+	 * @param {String} input The domain name or email address to convert, as a
+	 * Unicode string.
+	 * @returns {String} The Punycode representation of the given domain name or
+	 * email address.
+	 */
+	function toASCII(input) {
+		return mapDomain(input, function(string) {
+			return regexNonASCII.test(string)
+				? 'xn--' + encode(string)
+				: string;
+		});
+	}
+
+	/*--------------------------------------------------------------------------*/
+
+	/** Define the public API */
+	punycode = {
+		/**
+		 * A string representing the current Punycode.js version number.
+		 * @memberOf punycode
+		 * @type String
+		 */
+		'version': '1.4.1',
+		/**
+		 * An object of methods to convert from JavaScript's internal character
+		 * representation (UCS-2) to Unicode code points, and back.
+		 * @see <https://mathiasbynens.be/notes/javascript-encoding>
+		 * @memberOf punycode
+		 * @type Object
+		 */
+		'ucs2': {
+			'decode': ucs2decode,
+			'encode': ucs2encode
+		},
+		'decode': decode,
+		'encode': encode,
+		'toASCII': toASCII,
+		'toUnicode': toUnicode
+	};
+
+	/** Expose `punycode` */
+	// Some AMD build optimizers, like r.js, check for specific condition patterns
+	// like the following:
+	if (
+		true
+	) {
+		!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {
+			return punycode;
+		}).call(exports, __webpack_require__, exports, module),
+				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+	} else if (freeExports && freeModule) {
+		if (module.exports == freeExports) {
+			// in Node.js, io.js, or RingoJS v0.8.0+
+			freeModule.exports = punycode;
+		} else {
+			// in Narwhal or RingoJS v0.7.0-
+			for (key in punycode) {
+				punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
+			}
+		}
+	} else {
+		// in Rhino or a web browser
+		root.punycode = punycode;
+	}
+
+}(this));
+
+/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(793)(module), __webpack_require__(792)))
+
+/***/ }),
+
 /***/ 3651:
 /***/ (function(module, exports, __webpack_require__) {
 
 /* 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 networkRequest = __webpack_require__(3653);
@@ -4612,17 +5152,17 @@ module.exports = function wasm() {
 
 /***/ }),
 
 /***/ 3807:
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 /* WEBPACK VAR INJECTION */(function(Buffer) {
-const punycode = __webpack_require__(916);
+const punycode = __webpack_require__(3641);
 const tr46 = __webpack_require__(3819);
 
 const infra = __webpack_require__(3811);
 const { percentEncode, percentDecode } = __webpack_require__(3808);
 
 const specialSchemes = {
   ftp: 21,
   file: null,
@@ -7672,17 +8212,17 @@ exports.implementation = class URLImpl {
 /***/ }),
 
 /***/ 3819:
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
-const punycode = __webpack_require__(916);
+const punycode = __webpack_require__(3641);
 const regexes = __webpack_require__(3820);
 const mappingTable = __webpack_require__(3821);
 
 function containsNonASCII(str) {
   return /[^\x00-\x7F]/.test(str);
 }
 
 function findStatus(val, { useSTD3ASCIIRules }) {
@@ -12888,552 +13428,12 @@ exports.write = function (buffer, value,
 
 var toString = {}.toString;
 
 module.exports = Array.isArray || function (arr) {
   return toString.call(arr) == '[object Array]';
 };
 
 
-/***/ }),
-
-/***/ 916:
-/***/ (function(module, exports, __webpack_require__) {
-
-/* WEBPACK VAR INJECTION */(function(module, global) {var __WEBPACK_AMD_DEFINE_RESULT__;/*! https://mths.be/punycode v1.4.1 by @mathias */
-;(function(root) {
-
-	/** Detect free variables */
-	var freeExports = typeof exports == 'object' && exports &&
-		!exports.nodeType && exports;
-	var freeModule = typeof module == 'object' && module &&
-		!module.nodeType && module;
-	var freeGlobal = typeof global == 'object' && global;
-	if (
-		freeGlobal.global === freeGlobal ||
-		freeGlobal.window === freeGlobal ||
-		freeGlobal.self === freeGlobal
-	) {
-		root = freeGlobal;
-	}
-
-	/**
-	 * The `punycode` object.
-	 * @name punycode
-	 * @type Object
-	 */
-	var punycode,
-
-	/** Highest positive signed 32-bit float value */
-	maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
-
-	/** Bootstring parameters */
-	base = 36,
-	tMin = 1,
-	tMax = 26,
-	skew = 38,
-	damp = 700,
-	initialBias = 72,
-	initialN = 128, // 0x80
-	delimiter = '-', // '\x2D'
-
-	/** Regular expressions */
-	regexPunycode = /^xn--/,
-	regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
-	regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
-
-	/** Error messages */
-	errors = {
-		'overflow': 'Overflow: input needs wider integers to process',
-		'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
-		'invalid-input': 'Invalid input'
-	},
-
-	/** Convenience shortcuts */
-	baseMinusTMin = base - tMin,
-	floor = Math.floor,
-	stringFromCharCode = String.fromCharCode,
-
-	/** Temporary variable */
-	key;
-
-	/*--------------------------------------------------------------------------*/
-
-	/**
-	 * A generic error utility function.
-	 * @private
-	 * @param {String} type The error type.
-	 * @returns {Error} Throws a `RangeError` with the applicable error message.
-	 */
-	function error(type) {
-		throw new RangeError(errors[type]);
-	}
-
-	/**
-	 * A generic `Array#map` utility function.
-	 * @private
-	 * @param {Array} array The array to iterate over.
-	 * @param {Function} callback The function that gets called for every array
-	 * item.
-	 * @returns {Array} A new array of values returned by the callback function.
-	 */
-	function map(array, fn) {
-		var length = array.length;
-		var result = [];
-		while (length--) {
-			result[length] = fn(array[length]);
-		}
-		return result;
-	}
-
-	/**
-	 * A simple `Array#map`-like wrapper to work with domain name strings or email
-	 * addresses.
-	 * @private
-	 * @param {String} domain The domain name or email address.
-	 * @param {Function} callback The function that gets called for every
-	 * character.
-	 * @returns {Array} A new string of characters returned by the callback
-	 * function.
-	 */
-	function mapDomain(string, fn) {
-		var parts = string.split('@');
-		var result = '';
-		if (parts.length > 1) {
-			// In email addresses, only the domain name should be punycoded. Leave
-			// the local part (i.e. everything up to `@`) intact.
-			result = parts[0] + '@';
-			string = parts[1];
-		}
-		// Avoid `split(regex)` for IE8 compatibility. See #17.
-		string = string.replace(regexSeparators, '\x2E');
-		var labels = string.split('.');
-		var encoded = map(labels, fn).join('.');
-		return result + encoded;
-	}
-
-	/**
-	 * Creates an array containing the numeric code points of each Unicode
-	 * character in the string. While JavaScript uses UCS-2 internally,
-	 * this function will convert a pair of surrogate halves (each of which
-	 * UCS-2 exposes as separate characters) into a single code point,
-	 * matching UTF-16.
-	 * @see `punycode.ucs2.encode`
-	 * @see <https://mathiasbynens.be/notes/javascript-encoding>
-	 * @memberOf punycode.ucs2
-	 * @name decode
-	 * @param {String} string The Unicode input string (UCS-2).
-	 * @returns {Array} The new array of code points.
-	 */
-	function ucs2decode(string) {
-		var output = [],
-		    counter = 0,
-		    length = string.length,
-		    value,
-		    extra;
-		while (counter < length) {
-			value = string.charCodeAt(counter++);
-			if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
-				// high surrogate, and there is a next character
-				extra = string.charCodeAt(counter++);
-				if ((extra & 0xFC00) == 0xDC00) { // low surrogate
-					output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
-				} else {
-					// unmatched surrogate; only append this code unit, in case the next
-					// code unit is the high surrogate of a surrogate pair
-					output.push(value);
-					counter--;
-				}
-			} else {
-				output.push(value);
-			}
-		}
-		return output;
-	}
-
-	/**
-	 * Creates a string based on an array of numeric code points.
-	 * @see `punycode.ucs2.decode`
-	 * @memberOf punycode.ucs2
-	 * @name encode
-	 * @param {Array} codePoints The array of numeric code points.
-	 * @returns {String} The new Unicode string (UCS-2).
-	 */
-	function ucs2encode(array) {
-		return map(array, function(value) {
-			var output = '';
-			if (value > 0xFFFF) {
-				value -= 0x10000;
-				output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
-				value = 0xDC00 | value & 0x3FF;
-			}
-			output += stringFromCharCode(value);
-			return output;
-		}).join('');
-	}
-
-	/**
-	 * Converts a basic code point into a digit/integer.
-	 * @see `digitToBasic()`
-	 * @private
-	 * @param {Number} codePoint The basic numeric code point value.
-	 * @returns {Number} The numeric value of a basic code point (for use in
-	 * representing integers) in the range `0` to `base - 1`, or `base` if
-	 * the code point does not represent a value.
-	 */
-	function basicToDigit(codePoint) {
-		if (codePoint - 48 < 10) {
-			return codePoint - 22;
-		}
-		if (codePoint - 65 < 26) {
-			return codePoint - 65;
-		}
-		if (codePoint - 97 < 26) {
-			return codePoint - 97;
-		}
-		return base;
-	}
-
-	/**
-	 * Converts a digit/integer into a basic code point.
-	 * @see `basicToDigit()`
-	 * @private
-	 * @param {Number} digit The numeric value of a basic code point.
-	 * @returns {Number} The basic code point whose value (when used for
-	 * representing integers) is `digit`, which needs to be in the range
-	 * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
-	 * used; else, the lowercase form is used. The behavior is undefined
-	 * if `flag` is non-zero and `digit` has no uppercase form.
-	 */
-	function digitToBasic(digit, flag) {
-		//  0..25 map to ASCII a..z or A..Z
-		// 26..35 map to ASCII 0..9
-		return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
-	}
-
-	/**
-	 * Bias adaptation function as per section 3.4 of RFC 3492.
-	 * https://tools.ietf.org/html/rfc3492#section-3.4
-	 * @private
-	 */
-	function adapt(delta, numPoints, firstTime) {
-		var k = 0;