Merge inbound to m-c. a=merge
authorRyan VanderMeulen <ryanvm@gmail.com>
Fri, 15 Sep 2017 14:20:02 -0400
changeset 665623 7aceaf8bcb9f582db0f93488b48ef7019e348dba
parent 665597 31992a5c3d64ade078accdaab8ac4ffb5e43a9d7 (current diff)
parent 665508 0e14317d2f6c454e86549fe84d6067e1745a76c5 (diff)
child 665624 2c23aed729dc73adb54c9f9e850d45564ba8e9e7
child 665626 f954ddf67d55cb5b5cb623e7adc95f2637742a91
child 665653 a4b997ed2e547de46c0aca651c877f2de7c27f91
child 665657 eba07bb1d697ccb0bcc822bc80e7683bc0ca1879
child 665663 ba35082dfa3bbf3ad405cd4e1192a51aa4b7e0ca
child 665665 6ebee32e288b5d02b96fc01b393f2e64a6c6820d
child 665667 e4ef594276e158c4daf3d66aceade29f1e59e952
child 665672 3daddc00d9e2cc724a3a68024514f64f8f49114e
child 665698 e65c63e20f93eda01cee102363f61cc5d50e55f6
child 665759 493618b5cb2104b05e4a14f427b27df26e01720a
child 665807 8d514e6d48309eb1c03af5c148ea139693e6c62d
child 665973 f0e1bee97071b45ee1d3380a9dec69c20bd8ffd6
child 666034 d942754fc5002902fe91ab012e4c5a1bb868288f
child 666035 bd61685d80a600bceca445d79922d0c0655e25a9
child 666038 638b3e133d5b97ab834ffa32c2b80c69699f3e4a
child 666465 2f32b6d837d0d77cafe1a17fd0e5dee2331464e7
child 666521 f3c0946e214d654ff3b6464544f929bfb9974246
child 666523 8e414cfceae68cf4adc56ed60f6178accf43c92c
child 666525 cc0d4711a0f4d38980a67ed64054cf96b5683a1b
child 667305 30986aa380b2d4d1fea917cd51d90b3b2f748870
child 667449 e2edeeaf076fa8a4505dd6993540fe138763d2df
child 667466 1cb59fa926c5475be1f12eee13e6f4443bbc1c3c
child 667696 5c19364ea8c2986777442c42d357c06d07eb01d5
child 667759 cdcb9cda69eac57c264de6f254583c2c791aebba
child 668453 650c0060e4ba57b337d44ee969f96a26d076885e
push id80126
push userkgupta@mozilla.com
push dateFri, 15 Sep 2017 19:42:41 +0000
reviewersmerge
milestone57.0a1
Merge inbound to m-c. a=merge
browser/themes/shared/tabs.inc.css
dom/webauthn/u2f-hid-rs/src/android/mod.rs
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -5837,20 +5837,18 @@
           const nsIWebProgress = Components.interfaces.nsIWebProgress;
           const filter = Components.classes["@mozilla.org/appshell/component/browser-status-filter;1"]
                                    .createInstance(nsIWebProgress);
           filter.addProgressListener(tabListener, nsIWebProgress.NOTIFY_ALL);
           this._tabListeners.set(this.mCurrentTab, tabListener);
           this._tabFilters.set(this.mCurrentTab, filter);
           this.webProgress.addProgressListener(filter, nsIWebProgress.NOTIFY_ALL);
 
-          this.style.backgroundColor =
-            Services.prefs.getBoolPref("browser.display.use_system_colors") ?
-              "-moz-default-background-color" :
-              Services.prefs.getCharPref("browser.display.background_color");
+          if (Services.prefs.getBoolPref("browser.display.use_system_colors"))
+            this.style.backgroundColor = "-moz-default-background-color";
 
           let messageManager = window.getGroupMessageManager("browsers");
 
           let remote = window.QueryInterface(Ci.nsIInterfaceRequestor)
             .getInterface(Ci.nsIWebNavigation)
             .QueryInterface(Ci.nsILoadContext)
             .useRemoteTabs;
           if (remote) {
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -381,16 +381,18 @@ These should match what Safari and other
 <!ENTITY appMenuRemoteTabs.noclients.title "No synced tabs… yet!">
 <!ENTITY appMenuRemoteTabs.noclients.subtitle "Want to see your tabs from other devices here?">
 <!ENTITY appMenuRemoteTabs.openprefs.label "Sync Preferences">
 <!ENTITY appMenuRemoteTabs.notsignedin.label "Sign in to view a list of tabs from your other devices.">
 <!ENTITY appMenuRemoteTabs.signin.label "Sign in to Sync">
 <!ENTITY appMenuRemoteTabs.managedevices.label "Manage Devices…">
 <!ENTITY appMenuRemoteTabs.sidebar.label "View Synced Tabs Sidebar">
 
+<!ENTITY appMenuRecentHighlights.label "Recent Highlights">
+
 <!ENTITY customizeMenu.addToToolbar.label "Add to Toolbar">
 <!ENTITY customizeMenu.addToToolbar.accesskey "A">
 <!ENTITY customizeMenu.addToPanel.label "Add to Menu">
 <!ENTITY customizeMenu.addToPanel.accesskey "M">
 <!-- LOCALIZATION NOTE (customizeMenu.addToOverflowMenu.label,
      customizeMenu.pinToOverflowMenu.label, customizeMenu.unpinFromOverflowMenu.label)
      The overflow menu is the menu that appears if you click the chevron (>> button)
      in the location bar. These labels are only used in Photon, where you can put
--- a/browser/themes/shared/tabs.inc.css
+++ b/browser/themes/shared/tabs.inc.css
@@ -20,16 +20,26 @@
 :root[uidensity=touch] {
   --tab-min-height: 41px;
 }
 
 :root:-moz-lwtheme {
   --tab-line-color: var(--lwt-accent-color);
 }
 
+tabbrowser {
+  /* Value for --in-content-page-background in in-content/common.inc.css */
+  background-color: #f9f9fa;
+}
+
+:root[privatebrowsingmode=temporary] tabbrowser {
+  /* Value for --in-content-page-background in aboutPrivateBrowsing.css */
+  background-color: #25003e;
+}
+
 #tabbrowser-tabs,
 #tabbrowser-tabs > .tabbrowser-arrowscrollbox,
 .tabbrowser-tabs[positionpinnedtabs] > .tabbrowser-tab[pinned] {
   min-height: var(--tab-min-height);
 }
 
 .tab-stack {
   min-height: inherit;
--- a/devtools/client/debugger/new/debugger.css
+++ b/devtools/client/debugger/new/debugger.css
@@ -1071,17 +1071,17 @@ html[dir="rtl"] .managed-tree .tree .nod
   margin-left: 5px;
 }
 
 .project-text-search .result {
   font-family: Menlo, monospace;
 }
 
 .project-text-search .result.focused {
-  background-color: var(--theme-codemirror-gutter-background);
+  background-color: var(--search-overlays-semitransparent);
 }
 
 .project-text-search .result .query-match {
   background-color: var(--theme-selection-background);
   color: white;
   padding: 1px 4px;
   margin: 0 2px 0 2px;
   border-radius: 2px;
@@ -1089,32 +1089,40 @@ html[dir="rtl"] .managed-tree .tree .nod
 
 .project-text-search .result.focused .line-number {
   font-weight: bolder;
 }
 
 .project-text-search .result .line-number {
   margin-right: 1em;
   width: 2em;
+  margin-left: 0.8em;
+}
+
+.project-text-search .no-result-msg {
+  color: var(--theme-body-color-inactive);
+  font-size: 24px;
+  padding: 4px;
+  word-break: break-all;
 }
 
 .project-text-search .file-result {
   font-weight: bold;
   line-height: 20px;
   cursor: default;
   padding: 2px 0 2px 5px;
   font-size: 12px;
 }
 
 .project-text-search .file-result .arrow {
   margin: 2px 0 2px 0;
 }
 
 .project-text-search .file-result.focused {
-  background-color: var(--theme-codemirror-gutter-background);
+  background-color: var(--search-overlays-semitransparent);
 }
 
 .project-text-search .line-match {
   display: "flex";
   grow: 1;
 }
 
 .project-text-search .search-field {
@@ -1186,16 +1194,24 @@ html[dir="rtl"] .managed-tree .tree .nod
   background-color: var(--theme-selection-background);
   color: white;
 }
 
 .theme-dark .result-list.small li.selected {
   background-color: var(--theme-body-background);
 }
 
+.theme-dark .result-list li:hover {
+  background: var(--grey-70);
+}
+
+.theme-dark .result-list li.selected {
+  background: var(--grey-70);
+}
+
 .result-list li .title {
   line-height: 1.5em;
   word-break: break-all;
 }
 
 .result-list li.selected .title {
   color: white;
 }
@@ -1229,17 +1245,17 @@ html[dir="rtl"] .managed-tree .tree .nod
   top: 30px;
   left: 0;
   width: calc(100% - 1px);
   height: calc(100% - 31px);
   display: flex;
   flex-direction: column;
   z-index: 200;
   background-color: var(--theme-body-background);
-  overflow-y: auto;
+  overflow-y: hidden;
 }
 
 .searchinput-container {
   display: flex;
   border-bottom: 1px solid var(--theme-splitter-color);
 }
 
 .theme-dark .result-list li .subtitle {
@@ -1309,16 +1325,17 @@ html[dir="rtl"] .managed-tree .tree .nod
 }
 
 .sources-header-info {
   font-size: 12px;
   color: var(--theme-comment-alt);
   font-weight: lighter;
   white-space: nowrap;
   padding-inline-end: 10px;
+  cursor: default;
 }
 
 .sources-list {
   flex: 1;
   display: flex;
   overflow-x: hidden;
   overflow-y: auto;
 }
@@ -1378,16 +1395,17 @@ html[dir="rtl"] .managed-tree .tree .nod
   border-bottom-right-radius: 2px;
   display: inline-flex;
   position: relative;
   transition: all 0.25s ease;
   overflow: hidden;
   padding: 5px;
   margin-bottom: 0px;
   margin-top: -1px;
+  cursor: default;
 }
 
 .source-footer .tab:hover {
   background-color: var(--theme-toolbar-background-alt);
   border-color: var(--theme-splitter-color);
 }
 
 .source-footer .tab.active {
@@ -1399,28 +1417,38 @@ html[dir="rtl"] .managed-tree .tree .nod
 .source-footer .tab.active path,
 .source-footer .tab:hover path {
   fill: var(--theme-body-color);
 }
 .outline {
   overflow-y: auto;
 }
 
+.outline .outline-pane-info {
+  width: 100%;
+  font-style: italic;
+  text-align: center;
+  padding: 0.5em;
+  user-select: none;
+  font-size: 12px;
+}
+
 .outline-list {
   list-style-type: none;
   padding-left: 0px;
   width: 100%;
 }
 
 .outline-list__element {
   color: blue;
   padding-bottom: 0.2rem;
   padding-left: 1rem;
   padding-right: 0.5rem;
   padding-top: 0.2rem;
+  cursor: default;
 }
 
 .outline-list__element:hover {
   background: var(--theme-toolbar-background-hover);
 }
 .function-signature {
   align-self: center;
 }
@@ -2387,35 +2415,16 @@ html[dir="rtl"] .editor-mount {
   0% {
     background-color: var(--theme-content-color3);
   }
   100% {
     background-color: transparent;
   }
 }
 
-.welcomebox {
-  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;
-  text-align: center;
-  font-size: 1.25em;
-  color: var(--theme-comment-alt);
-  background-color: var(--theme-tab-toolbar-background);
-  font-weight: lighter;
-  z-index: 100;
-  -moz-user-select: none;
-  user-select: none;
-}
-
 .CodeMirror-guttermarker-subtle {
   visibility: hidden;
 }
 
 .visible {
   visibility: visible;
 }
 .cm-highlight {
@@ -2503,16 +2512,17 @@ html .breakpoints-list .breakpoint.pause
   margin-inline-start: 0;
   vertical-align: -2px;
 }
 
 .breakpoints-list .breakpoint-label {
   display: inline-block;
   padding-inline-start: 2px;
   padding-bottom: 4px;
+  cursor: default;
 }
 
 .breakpoints-list .pause-indicator {
   flex: 0 1 content;
   order: 3;
 }
 
 :root.theme-light .breakpoint-snippet,
@@ -2617,33 +2627,20 @@ html .breakpoints-list .breakpoint.pause
 
 .expression-container:hover .close-btn {
   display: block;
 }
 
 .expression-input {
   max-width: 50%;
 }
-
-.expression-separator {
-  padding: 0px 5px;
-}
-
-.expression-value {
-  overflow-x: scroll;
-  color: var(--theme-content-color2);
-  max-width: 50% !important;
-}
-
-.expression-error {
-  color: var(--theme-highlight-red);
-}
 .frames ul .frames-group .group,
 .frames ul .frames-group .group .location {
   font-weight: 500;
+  cursor: default;
 }
 
 .frames ul .frames-group.expanded .group,
 .frames ul .frames-group.expanded .group .location {
   color: var(--theme-highlight-blue);
 }
 
 .frames ul .frames-group.expanded .react path {
@@ -2664,16 +2661,17 @@ html .breakpoints-list .breakpoint.pause
   padding: 10px 10px 10px 20px;
   white-space: normal;
   opacity: 0.6;
   font-size: 12px;
   flex: 0 1 auto;
   text-align: center;
   font-style: italic;
   font-weight: 300;
+  cursor: default;
 }
 
 .theme-dark .secondary-panes .why-paused {
   color: white;
 }
 
 .why-paused .message {
   font-size: 10px;
@@ -2700,24 +2698,16 @@ html .breakpoints-list .breakpoint.pause
   margin: 0;
 }
 
 .frames ul li * {
   -moz-user-select: none;
   user-select: none;
 }
 
-.frames ul li:nth-of-type(2n) {
-  background-color: var(--theme-tab-toolbar-background);
-}
-
-.theme-dark .frames ul li:nth-of-type(2n) {
-  background-color: var(--theme-toolbar-background-alt);
-}
-
 .frames .location {
   font-weight: lighter;
   display: flex;
   justify-content: space-between;
   flex-direction: row;
   align-items: center;
   margin: 0;
 }
@@ -2739,17 +2729,16 @@ html .breakpoints-list .breakpoint.pause
 }
 
 .frames ul li:hover,
 .frames ul li:focus {
   background-color: var(--theme-toolbar-background-alt);
   outline: none;
 }
 
-.theme-dark .frames ul li:hover,
 .theme-dark .frames ul li:focus {
   background-color: var(--theme-tab-toolbar-background);
 }
 
 .frames ul li.selected {
   background-color: var(--theme-selection-background);
   color: white;
 }
@@ -2759,21 +2748,16 @@ html .breakpoints-list .breakpoint.pause
 }
 
 :root.theme-light .frames ul li.selected .location,
 :root.theme-firebug .frames ul li.selected .location,
 :root.theme-dark .frames ul li.selected .location {
   color: white;
 }
 
-:root.theme-dark .frames ul li:hover .location,
-:root.theme-dark .frames ul li.selected .location {
-  opacity: 1;
-}
-
 .show-more {
   text-align: center;
   padding: 8px 0px;
   margin: 7px 10px 7px 7px;
   border: 1px solid var(--theme-splitter-color);
   background-color: var(--theme-tab-toolbar-background);
 }
 
@@ -2860,16 +2844,17 @@ html .breakpoints-list .breakpoint.pause
   height: 24px;
   align-items: center;
 
   -webkit-user-select: none;
   -moz-user-select: none;
   -ms-user-select: none;
   -o-user-select: none;
   user-select: none;
+  cursor: default;
 }
 
 .accordion ._header:hover {
   background-color: var(--theme-toolbar-background-hover);
 }
 
 .accordion ._header button svg,
 .accordion ._header:hover button svg {
@@ -3052,16 +3037,17 @@ html .command-bar > button:disabled {
 }
 
 .pane .pane-info {
   font-style: italic;
   text-align: center;
   padding: 0.5em;
   -moz-user-select: none;
   user-select: none;
+  cursor: default;
 }
 
 .theme-dark .secondary-panes .accordion .arrow svg {
   fill: var(--theme-content-color3);
 }
 .welcomebox {
   width: calc(100% - 1px);
 
@@ -3072,16 +3058,17 @@ html .command-bar > button:disabled {
   left: 0;
   padding: 50px 0 0 0;
   text-align: center;
   font-size: 1.25em;
   color: var(--theme-comment-alt);
   background-color: var(--theme-toolbar-background);
   font-weight: lighter;
   z-index: 100;
+  user-select: none;
 }
 
 .theme-dark .welcomebox {
   background-color: var(--theme-body-background);
 }
 
 .alignlabel {
   display: inline-block;
@@ -3153,17 +3140,18 @@ html .welcomebox .toggle-button-end.coll
   display: inline-flex;
   align-items: flex-end;
   position: relative;
   transition: all 0.15s ease;
   min-width: 40px;
   overflow: hidden;
   padding: 5px;
   margin-inline-start: 3px;
-  margin-top: 4px;
+  margin-top: 3px;
+  cursor: default;
 }
 
 .source-tab:hover {
   background-color: var(--theme-toolbar-background-alt);
   border-color: var(--theme-splitter-color);
 }
 
 .source-tab.active {
--- a/devtools/client/debugger/new/debugger.js
+++ b/devtools/client/debugger/new/debugger.js
@@ -569,20 +569,26 @@ function createParentMap(tree) {
   }
 
   // Don't link each top-level path to the "root" node because the
   // user never sees the root
   tree.contents.forEach(_traverse);
   return map;
 }
 
-function getRelativePath(path) {
-  var re = /(http(?:s?):\/\/(?:www\.)?[a-z0-9\-.]+)\/(.*)/i;
-  var matches = path.match(re);
-  return matches ? matches[2] : "";
+function getRelativePath(url) {
+  var _parse2 = (0, _url.parse)(url),
+      pathname = _parse2.pathname;
+
+  if (!pathname) {
+    return url;
+  }
+  var path = pathname.split("/");
+  path.shift();
+  return path.join("/");
 }
 
 /***/ }),
 /* 19 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
@@ -1831,16 +1837,18 @@ exports.clearSearchQuery = clearSearchQu
 exports.clearSearchResults = clearSearchResults;
 exports.searchSources = searchSources;
 exports.searchSource = searchSource;
 
 var _search = __webpack_require__(1115);
 
 var _selectors = __webpack_require__(242);
 
+var _source = __webpack_require__(233);
+
 var _sources = __webpack_require__(254);
 
 function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
 
 /* 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/. */
 
@@ -1882,36 +1890,42 @@ function searchSources(query) {
       var dispatch = _ref5.dispatch,
           getState = _ref5.getState;
 
       yield dispatch(clearSearchResults());
       yield dispatch(addSearchQuery(query));
       yield dispatch((0, _sources.loadAllSources)());
       var sources = (0, _selectors.getSources)(getState());
       var validSources = sources.valueSeq().filter(function (source) {
-        return source.has("text");
+        return (0, _source.isLoaded)(source.toJS()) && !(0, _source.isThirdParty)(source.toJS());
       }).toJS();
 
       for (var source of validSources) {
-        yield dispatch(searchSource(source, query));
+        yield dispatch(searchSource(source.id, query));
       }
     });
 
     return function (_x) {
       return _ref4.apply(this, arguments);
     };
   })();
 }
 
-function searchSource(source, query) {
+function searchSource(sourceId, query) {
   return (() => {
     var _ref6 = _asyncToGenerator(function* (_ref7) {
       var dispatch = _ref7.dispatch,
           getState = _ref7.getState;
 
+      var sourceRecord = (0, _selectors.getSource)(getState(), sourceId);
+      if (!sourceRecord) {
+        return;
+      }
+
+      var source = sourceRecord.toJS();
       var matches = yield (0, _search.findSourceMatches)(source, query);
       dispatch({
         type: "ADD_SEARCH_RESULT",
         result: {
           sourceId: source.id,
           filepath: source.url,
           matches
         }
@@ -5913,17 +5927,17 @@ var _require5 = __webpack_require__(828)
     isDevelopment = _require5.isDevelopment;
 
 var L10N = __webpack_require__(185);
 
 var _require6 = __webpack_require__(1130),
     showMenu = _require6.showMenu,
     buildMenu = _require6.buildMenu;
 
-setConfig({"environment":"firefox-panel","logging":false,"clientLogging":false,"firefox":{"mcPath":"./firefox"},"workers":{"parserURL":"resource://devtools/client/debugger/new/parser-worker.js","prettyPrintURL":"resource://devtools/client/debugger/new/pretty-print-worker.js","searchURL":"resource://devtools/client/debugger/new/search-worker.js"},"features":{"blackbox":{"enabled":true},"chromeScopes":{"enabled":false},"eventListeners":{"enabled":false},"codeCoverage":{"enabled":false},"codeFolding":{"enabled":false},"searchNav":{"enabled":true},"collapseFrame":{"enabled":true},"outline":{"enabled":true},"wasm":{"enabled":true}}});
+setConfig({"environment":"firefox-panel","logging":false,"clientLogging":false,"firefox":{"mcPath":"./firefox"},"workers":{"parserURL":"resource://devtools/client/debugger/new/parser-worker.js","prettyPrintURL":"resource://devtools/client/debugger/new/pretty-print-worker.js","searchURL":"resource://devtools/client/debugger/new/search-worker.js"},"features":{"blackbox":{"enabled":true},"chromeScopes":{"enabled":false},"eventListeners":{"enabled":false},"codeCoverage":{"enabled":false},"codeFolding":{"enabled":false},"searchNav":{"enabled":true},"collapseFrame":{"enabled":true},"outline":{"enabled":true}}});
 
 // Set various flags before requiring app code.
 if (getValue("logging.client")) {
   // DevToolsUtils.dumpn.wantLogging = true;
 }
 
 var _require7 = __webpack_require__(885),
     firefox = _require7.firefox,
@@ -15549,32 +15563,26 @@ var history = exports.history = function
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.promise = exports.PROMISE = undefined;
 
-var _defer = __webpack_require__(194);
-
-var _defer2 = _interopRequireDefault(_defer);
-
 var _lodash = __webpack_require__(2);
 
 var _DevToolsUtils = __webpack_require__(222);
 
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+/* 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/. */
 
 var seqIdVal = 1;
 
-/* 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/. */
-
 function seqIdGen() {
   return seqIdVal++;
 }
 
 function filterAction(action) {
   return (0, _lodash.fromPairs)((0, _lodash.toPairs)(action).filter(pair => pair[0] !== PROMISE));
 }
 
@@ -15593,67 +15601,43 @@ function promiseMiddleware(_ref) {
     // Create a new action that doesn't have the promise field and has
     // the `seqId` field that represents the sequence id
     action = Object.assign(filterAction(action), { seqId });
 
     dispatch(Object.assign({}, action, { status: "start" }));
 
     // Return the promise so action creators can still compose if they
     // want to.
-    var deferred = (0, _defer2.default)();
-    promiseInst.then(value => {
-      (0, _DevToolsUtils.executeSoon)(() => {
-        dispatch(Object.assign({}, action, {
-          status: "done",
-          value: value
-        }));
-        deferred.resolve(value);
-      });
-    }, error => {
-      (0, _DevToolsUtils.executeSoon)(() => {
-        dispatch(Object.assign({}, action, {
-          status: "error",
-          error: error.message || error
-        }));
-        deferred.reject(error);
-      });
-    });
-    return deferred.promise;
+    return new Promise((resolve, reject) => {
+      promiseInst.then(value => {
+        (0, _DevToolsUtils.executeSoon)(() => {
+          dispatch(Object.assign({}, action, {
+            status: "done",
+            value: value
+          }));
+          resolve(value);
+        });
+      }, error => {
+        (0, _DevToolsUtils.executeSoon)(() => {
+          dispatch(Object.assign({}, action, {
+            status: "error",
+            error: error.message || error
+          }));
+          reject(error);
+        });
+      });
+    });
   };
 }
 
 var PROMISE = exports.PROMISE = "@@dispatch/promise";
 exports.promise = promiseMiddleware;
 
 /***/ }),
-/* 194 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
-  value: true
-});
-exports.default = defer;
-function defer() {
-  var resolve = void 0; // eslint-disable-line no-unused-vars
-  var reject = void 0; // eslint-disable-line no-unused-vars
-  var promise = new Promise(function (innerResolve, innerReject) {
-    resolve = innerResolve;
-    reject = innerReject;
-  });
-  return {
-    resolve,
-    reject,
-    promise
-  };
-}
-
-/***/ }),
+/* 194 */,
 /* 195 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
@@ -15965,16 +15949,17 @@ if (isDevelopment()) {
   pref("devtools.debugger.pending-breakpoints", "{}");
   pref("devtools.debugger.expressions", "[]");
   pref("devtools.debugger.file-search-case-sensitive", false);
   pref("devtools.debugger.file-search-whole-word", false);
   pref("devtools.debugger.file-search-regex-match", false);
   pref("devtools.debugger.prefs-schema-version", "1.0.1");
   pref("devtools.debugger.project-text-search-enabled", true);
   pref("devtools.debugger.features.async-stepping", true);
+  pref("devtools.debugger.features.wasm", true);
 }
 
 const prefs = new PrefsHelper("devtools", {
   clientSourceMapsEnabled: ["Bool", "debugger.client-source-maps-enabled"],
   pauseOnExceptions: ["Bool", "debugger.pause-on-exceptions"],
   ignoreCaughtExceptions: ["Bool", "debugger.ignore-caught-exceptions"],
   callStackVisible: ["Bool", "debugger.call-stack-visible"],
   scopesVisible: ["Bool", "debugger.scopes-visible"],
@@ -16656,17 +16641,17 @@ exports.default = update;
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
-exports.isLoaded = exports.getMode = exports.getSourceLineCount = exports.getSourcePath = exports.getFilenameFromURL = exports.getFilename = exports.getRawSourceURL = exports.getPrettySourceURL = exports.shouldPrettyPrint = exports.isPretty = exports.isJavaScript = undefined;
+exports.isLoaded = exports.getMode = exports.getSourceLineCount = exports.getSourcePath = exports.getFilenameFromURL = exports.getFilename = exports.getRawSourceURL = exports.getPrettySourceURL = exports.shouldPrettyPrint = exports.isThirdParty = exports.isPretty = exports.isJavaScript = undefined;
 
 var _devtoolsSourceMap = __webpack_require__(898);
 
 var _utils = __webpack_require__(234);
 
 var _path = __webpack_require__(235);
 
 var _url = __webpack_require__(334);
@@ -16730,16 +16715,24 @@ function isJavaScript(url) {
 /**
  * @memberof utils/source
  * @static
  */
 function isPretty(source) {
   return source.url ? /formatted$/.test(source.url) : false;
 }
 
+function isThirdParty(source) {
+  if (!source || !source.url) {
+    return false;
+  }
+
+  return !!source.url.match(/(node_modules|bower_components)/);
+}
+
 /**
  * @memberof utils/source
  * @static
  */
 function getPrettySourceURL(url) {
   if (!url) {
     url = "";
   }
@@ -16879,16 +16872,17 @@ function getMode(source) {
 }
 
 function isLoaded(source) {
   return source.loadedState === "loaded";
 }
 
 exports.isJavaScript = isJavaScript;
 exports.isPretty = isPretty;
+exports.isThirdParty = isThirdParty;
 exports.shouldPrettyPrint = shouldPrettyPrint;
 exports.getPrettySourceURL = getPrettySourceURL;
 exports.getRawSourceURL = getRawSourceURL;
 exports.getFilename = getFilename;
 exports.getFilenameFromURL = getFilenameFromURL;
 exports.getSourcePath = getSourcePath;
 exports.getSourceLineCount = getSourceLineCount;
 exports.getMode = getMode;
@@ -17636,16 +17630,17 @@ exports.getActiveSearch = getActiveSearc
 exports.getFileSearchQueryState = getFileSearchQueryState;
 exports.getFileSearchModifierState = getFileSearchModifierState;
 exports.getSearchResults = getSearchResults;
 exports.getFrameworkGroupingState = getFrameworkGroupingState;
 exports.getSymbolSearchType = getSymbolSearchType;
 exports.getShownSource = getShownSource;
 exports.getPaneCollapse = getPaneCollapse;
 exports.getHighlightedLineRange = getHighlightedLineRange;
+exports.getConditionalBreakpointPanel = getConditionalBreakpointPanel;
 
 var _makeRecord = __webpack_require__(230);
 
 var _makeRecord2 = _interopRequireDefault(_makeRecord);
 
 var _prefs = __webpack_require__(226);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -17669,17 +17664,18 @@ var State = exports.State = (0, _makeRec
     matchIndex: -1,
     index: -1,
     count: 0
   },
   shownSource: "",
   startPanelCollapsed: _prefs.prefs.startPanelCollapsed,
   endPanelCollapsed: _prefs.prefs.endPanelCollapsed,
   frameworkGroupingOn: _prefs.prefs.frameworkGroupingOn,
-  highlightedLineRange: undefined
+  highlightedLineRange: undefined,
+  conditionalBreakpointPanel: null
 });
 
 function update() {
   var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : State();
   var action = arguments[1];
 
   switch (action.type) {
     case "TOGGLE_ACTIVE_SEARCH":
@@ -17755,16 +17751,19 @@ function update() {
         lineRange = { start: _start, end: _end, sourceId: _sourceId };
       }
 
       return state.set("highlightedLineRange", lineRange);
 
     case "CLEAR_HIGHLIGHT_LINES":
       return state.set("highlightedLineRange", {});
 
+    case "TOGGLE_CONDITIONAL_BREAKPOINT_PANEL":
+      return state.set("conditionalBreakpointPanel", action.line);
+
     default:
       {
         return state;
       }
   }
 }
 
 // NOTE: we'd like to have the app state fully typed
@@ -17804,16 +17803,20 @@ function getPaneCollapse(state, position
 
   return state.ui.get("endPanelCollapsed");
 }
 
 function getHighlightedLineRange(state) {
   return state.ui.get("highlightedLineRange");
 }
 
+function getConditionalBreakpointPanel(state) {
+  return state.ui.get("conditionalBreakpointPanel");
+}
+
 exports.default = update;
 
 /***/ }),
 /* 241 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
@@ -18450,24 +18453,18 @@ function addHiddenBreakpoint(location) {
  */
 function removeBreakpoint(location) {
   return (_ref6) => {
     var dispatch = _ref6.dispatch,
         getState = _ref6.getState,
         client = _ref6.client;
 
     var bp = (0, _selectors.getBreakpoint)(getState(), location);
-    if (!bp) {
-      throw new Error("attempt to remove breakpoint that does not exist");
-    }
-
-    if (bp.loading) {
-      // TODO(jwl): make this wait until the breakpoint is saved if it
-      // is still loading
-      throw new Error("attempt to remove unsaved breakpoint");
+    if (!bp || bp.loading) {
+      return;
     }
 
     // If the breakpoint is already disabled, we don't need to communicate
     // with the server. We just need to dispatch an action
     // simulating a successful server request
     if (bp.disabled) {
       return dispatch({
         type: "REMOVE_BREAKPOINT",
@@ -18496,18 +18493,18 @@ function enableBreakpoint(location) {
   return (() => {
     var _ref7 = _asyncToGenerator(function* (_ref8) {
       var dispatch = _ref8.dispatch,
           getState = _ref8.getState,
           client = _ref8.client,
           sourceMaps = _ref8.sourceMaps;
 
       var breakpoint = (0, _selectors.getBreakpoint)(getState(), location);
-      if (!breakpoint) {
-        throw new Error("attempted to enable a breakpoint that does not exist");
+      if (!breakpoint || breakpoint.loading) {
+        return;
       }
 
       var action = { type: "ENABLE_BREAKPOINT", breakpoint };
       var promise = (0, _addBreakpoint2.default)(getState, client, sourceMaps, action);
       return dispatch({
         type: "ENABLE_BREAKPOINT",
         breakpoint,
         [_promise.PROMISE]: promise
@@ -18530,24 +18527,18 @@ function disableBreakpoint(location) {
   return (() => {
     var _ref9 = _asyncToGenerator(function* (_ref10) {
       var dispatch = _ref10.dispatch,
           getState = _ref10.getState,
           client = _ref10.client;
 
       var bp = (0, _selectors.getBreakpoint)(getState(), location);
 
-      if (!bp) {
-        throw new Error("attempt to disable a breakpoint that does not exist");
-      }
-
-      if (bp.loading) {
-        // TODO(jwl): make this wait until the breakpoint is saved if it
-        // is still loading
-        throw new Error("attempt to disable unsaved breakpoint");
+      if (!bp || bp.loading) {
+        return;
       }
 
       yield client.removeBreakpoint(bp.generatedLocation);
       var newBreakpoint = _extends({}, bp, { disabled: true });
 
       return dispatch({
         type: "DISABLE_BREAKPOINT",
         breakpoint: newBreakpoint
@@ -18722,19 +18713,17 @@ function setBreakpointCondition(location
           sourceMaps = _ref31.sourceMaps;
 
       var bp = (0, _selectors.getBreakpoint)(getState(), location);
       if (!bp) {
         return dispatch(addBreakpoint(location, condition));
       }
 
       if (bp.loading) {
-        // TODO(jwl): when this function is called, make sure the action
-        // creator waits for the breakpoint to exist
-        throw new Error("breakpoint must be saved");
+        return;
       }
 
       if (bp.disabled) {
         yield dispatch(enableBreakpoint(location));
         bp.disabled = !bp.disabled;
       }
 
       yield client.setBreakpointCondition(bp.id, location, condition, sourceMaps.isOriginalId(bp.location.sourceId));
@@ -18819,22 +18808,18 @@ function addOrToggleDisabledBreakpoint(l
 function toggleDisabledBreakpoint(line, column) {
   return (_ref34) => {
     var dispatch = _ref34.dispatch,
         getState = _ref34.getState,
         client = _ref34.client,
         sourceMaps = _ref34.sourceMaps;
 
     var bp = (0, _selectors.getBreakpointAtLocation)(getState(), { line, column });
-    if (bp && bp.loading) {
-      return;
-    }
-
-    if (!bp) {
-      throw new Error("attempt to disable breakpoint that does not exist");
+    if (!bp || bp.loading) {
+      return;
     }
 
     if (!bp.disabled) {
       return dispatch(disableBreakpoint(bp.location));
     }
     return dispatch(enableBreakpoint(bp.location));
   };
 }
@@ -19629,26 +19614,28 @@ var _assert2 = _interopRequireDefault(_a
 var _breakpoints = __webpack_require__(245);
 
 var _ast = __webpack_require__(1059);
 
 var _projectTextSearch = __webpack_require__(37);
 
 var _ui = __webpack_require__(321);
 
-var _source = __webpack_require__(233);
+var _source2 = __webpack_require__(233);
 
 var _createPrettySource = __webpack_require__(195);
 
 var _loadSourceText = __webpack_require__(1143);
 
 var _prefs = __webpack_require__(226);
 
 var _editor = __webpack_require__(257);
 
+var _sourceMaps = __webpack_require__(797);
+
 var _selectors = __webpack_require__(242);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
 
 /* 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
@@ -19660,16 +19647,21 @@ function _asyncToGenerator(fn) { return 
  */
 
 function newSource(source) {
   return (() => {
     var _ref4 = _asyncToGenerator(function* (_ref5) {
       var dispatch = _ref5.dispatch,
           getState = _ref5.getState;
 
+      var _source = (0, _selectors.getSource)(getState(), source.id);
+      if (_source) {
+        return;
+      }
+
       dispatch({ type: "ADD_SOURCE", source });
 
       if (_prefs.prefs.clientSourceMapsEnabled) {
         yield dispatch(loadSourceMap(source));
       }
 
       yield checkSelectedSource(getState(), dispatch, source);
       yield checkPendingBreakpoints(getState(), dispatch, source);
@@ -19719,17 +19711,20 @@ function loadSourceMap(generatedSource) 
         return;
       }
 
       var state = getState();
       var originalSources = urls.map(function (originalUrl) {
         return {
           url: originalUrl,
           id: sourceMaps.generatedToOriginalId(generatedSource.id, originalUrl),
-          isPrettyPrinted: false
+          isPrettyPrinted: false,
+          isWasm: false,
+          isBlackBoxed: false,
+          loadedState: "unloaded"
         };
       });
 
       dispatch({ type: "ADD_SOURCES", sources: originalSources });
 
       originalSources.forEach(function (source) {
         checkSelectedSource(state, dispatch, source);
         checkPendingBreakpoints(state, dispatch, source);
@@ -19836,17 +19831,17 @@ function jumpToMappedLocation(sourceLoca
 
       if (!client) {
         return;
       }
 
       var source = (0, _selectors.getSource)(getState(), sourceLocation.sourceId);
       var pairedLocation = void 0;
       if (sourceMaps.isOriginalId(sourceLocation.sourceId)) {
-        pairedLocation = yield sourceMaps.getGeneratedLocation(sourceLocation, source.toJS());
+        pairedLocation = yield (0, _sourceMaps.getGeneratedLocation)(getState(), source.toJS(), sourceLocation, sourceMaps);
       } else {
         pairedLocation = yield sourceMaps.getOriginalLocation(sourceLocation, source.toJS());
       }
 
       return dispatch(selectSource(pairedLocation.sourceId, { line: pairedLocation.line }));
     });
 
     return function (_x17) {
@@ -19932,26 +19927,26 @@ function togglePrettyPrint(sourceId) {
     var _ref18 = _asyncToGenerator(function* (_ref19) {
       var dispatch = _ref19.dispatch,
           getState = _ref19.getState,
           client = _ref19.client,
           sourceMaps = _ref19.sourceMaps;
 
       var source = (0, _selectors.getSource)(getState(), sourceId).toJS();
 
-      if (source && !(0, _source.isLoaded)(source)) {
+      if (source && !(0, _source2.isLoaded)(source)) {
         return {};
       }
 
       (0, _assert2.default)(sourceMaps.isGeneratedId(sourceId), "Pretty-printing only allowed on generated sources");
 
       var selectedLocation = (0, _selectors.getSelectedLocation)(getState());
       var selectedOriginalLocation = selectedLocation ? yield sourceMaps.getOriginalLocation(selectedLocation) : {};
 
-      var url = (0, _source.getPrettySourceURL)(source.url);
+      var url = (0, _source2.getPrettySourceURL)(source.url);
       var prettySource = (0, _selectors.getSourceByURL)(getState(), url);
 
       if (prettySource) {
         return dispatch(selectSource(prettySource.get("id"), {
           line: selectedOriginalLocation.line
         }));
       }
 
@@ -20010,21 +20005,25 @@ function loadAllSources() {
       var sources = (0, _selectors.getSources)(getState());
       var query = (0, _selectors.getTextSearchQuery)(getState());
       for (var _ref25 of sources) {
         var _ref26 = _slicedToArray(_ref25, 2);
 
         var src = _ref26[1];
 
         var source = src.toJS();
+        if ((0, _source2.isThirdParty)(source)) {
+          continue;
+        }
+
         yield dispatch((0, _loadSourceText.loadSourceText)(source));
         // If there is a current search query we search
         // each of the source texts as they get loaded
         if (query) {
-          yield dispatch((0, _projectTextSearch.searchSource)(source, query));
+          yield dispatch((0, _projectTextSearch.searchSource)(source.id, query));
         }
       }
     });
 
     return function (_x20) {
       return _ref23.apply(this, arguments);
     };
   })();
@@ -21302,16 +21301,17 @@ DebugLine.displayName = "DebugLine";
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.resumed = resumed;
+exports.continueToHere = continueToHere;
 exports.paused = paused;
 exports.pauseOnExceptions = pauseOnExceptions;
 exports.command = command;
 exports.stepIn = stepIn;
 exports.stepOver = stepOver;
 exports.stepOut = stepOut;
 exports.resume = resume;
 exports.breakOnNext = breakOnNext;
@@ -21366,30 +21366,54 @@ function resumed() {
     });
 
     if (!(0, _selectors.isStepping)(getState())) {
       dispatch((0, _expressions.evaluateExpressions)(null));
     }
   };
 }
 
+function continueToHere(line) {
+  return (() => {
+    var _ref2 = _asyncToGenerator(function* (_ref3) {
+      var dispatch = _ref3.dispatch,
+          getState = _ref3.getState,
+          client = _ref3.client,
+          sourceMaps = _ref3.sourceMaps;
+
+      var source = (0, _selectors.getSelectedSource)(getState()).toJS();
+
+      yield dispatch((0, _breakpoints.addHiddenBreakpoint)({
+        line,
+        column: undefined,
+        sourceId: source.id
+      }));
+      dispatch(command("resume"));
+    });
+
+    return function (_x) {
+      return _ref2.apply(this, arguments);
+    };
+  })();
+}
+
 /**
  * Debugger has just paused
  *
  * @param {object} pauseInfo
  * @memberof actions/pause
  * @static
  */
 function paused(pauseInfo) {
   return (() => {
-    var _ref2 = _asyncToGenerator(function* (_ref3) {
-      var dispatch = _ref3.dispatch,
-          getState = _ref3.getState,
-          client = _ref3.client,
-          sourceMaps = _ref3.sourceMaps;
+    var _ref4 = _asyncToGenerator(function* (_ref5) {
+      var dispatch = _ref5.dispatch,
+          getState = _ref5.getState,
+          client = _ref5.client,
+          sourceMaps = _ref5.sourceMaps;
       var frames = pauseInfo.frames,
           why = pauseInfo.why,
           loadedObjects = pauseInfo.loadedObjects;
 
 
       frames = yield (0, _pause.updateFrameLocations)(frames, sourceMaps);
       var frame = frames[0];
 
@@ -21399,36 +21423,41 @@ function paused(pauseInfo) {
         type: "PAUSED",
         pauseInfo: { why, frame, frames },
         frames: frames,
         scopes,
         selectedFrameId: frame.id,
         loadedObjects: loadedObjects || []
       });
 
+      var hiddenBreakpointLocation = (0, _breakpoints2.getHiddenBreakpointLocation)(getState());
+      if (hiddenBreakpointLocation) {
+        dispatch((0, _breakpoints.removeBreakpoint)(hiddenBreakpointLocation));
+      }
+
       dispatch((0, _expressions.evaluateExpressions)(frame.id));
 
       dispatch((0, _sources.selectSource)(frame.location.sourceId, { line: frame.location.line }));
     });
 
-    return function (_x) {
-      return _ref2.apply(this, arguments);
+    return function (_x2) {
+      return _ref4.apply(this, arguments);
     };
   })();
 }
 
 /**
  *
  * @memberof actions/pause
  * @static
  */
 function pauseOnExceptions(shouldPauseOnExceptions, shouldIgnoreCaughtExceptions) {
-  return (_ref4) => {
-    var dispatch = _ref4.dispatch,
-        client = _ref4.client;
+  return (_ref6) => {
+    var dispatch = _ref6.dispatch,
+        client = _ref6.client;
 
     dispatch({
       type: "PAUSE_ON_EXCEPTIONS",
       shouldPauseOnExceptions,
       shouldIgnoreCaughtExceptions,
       [_promise.PROMISE]: client.pauseOnExceptions(shouldPauseOnExceptions, shouldIgnoreCaughtExceptions)
     });
   };
@@ -21438,165 +21467,165 @@ function pauseOnExceptions(shouldPauseOn
  * Debugger commands like stepOver, stepIn, stepUp
  *
  * @param string $0.type
  * @memberof actions/pause
  * @static
  */
 function command(type) {
   return (() => {
-    var _ref5 = _asyncToGenerator(function* (_ref6) {
-      var dispatch = _ref6.dispatch,
-          client = _ref6.client;
+    var _ref7 = _asyncToGenerator(function* (_ref8) {
+      var dispatch = _ref8.dispatch,
+          client = _ref8.client;
 
       // execute debugger thread command e.g. stepIn, stepOver
       dispatch({ type: "COMMAND", value: { type } });
 
       yield client[type]();
 
       dispatch({ type: "CLEAR_COMMAND" });
     });
 
-    return function (_x2) {
-      return _ref5.apply(this, arguments);
+    return function (_x3) {
+      return _ref7.apply(this, arguments);
     };
   })();
 }
 
 /**
  * StepIn
  * @memberof actions/pause
  * @static
  * @returns {Function} {@link command}
  */
 function stepIn() {
-  return (_ref7) => {
-    var dispatch = _ref7.dispatch,
-        getState = _ref7.getState;
+  return (_ref9) => {
+    var dispatch = _ref9.dispatch,
+        getState = _ref9.getState;
 
     if ((0, _selectors.getPause)(getState())) {
       return dispatch(command("stepIn"));
     }
   };
 }
 
 /**
  * stepOver
  * @memberof actions/pause
  * @static
  * @returns {Function} {@link command}
  */
 function stepOver() {
-  return (_ref8) => {
-    var dispatch = _ref8.dispatch,
-        getState = _ref8.getState;
+  return (_ref10) => {
+    var dispatch = _ref10.dispatch,
+        getState = _ref10.getState;
 
     if ((0, _selectors.getPause)(getState())) {
       return dispatch(astCommand("stepOver"));
     }
   };
 }
 
 /**
  * stepOut
  * @memberof actions/pause
  * @static
  * @returns {Function} {@link command}
  */
 function stepOut() {
-  return (_ref9) => {
-    var dispatch = _ref9.dispatch,
-        getState = _ref9.getState;
+  return (_ref11) => {
+    var dispatch = _ref11.dispatch,
+        getState = _ref11.getState;
 
     if ((0, _selectors.getPause)(getState())) {
       return dispatch(command("stepOut"));
     }
   };
 }
 
 /**
  * resume
  * @memberof actions/pause
  * @static
  * @returns {Function} {@link command}
  */
 function resume() {
-  return (_ref10) => {
-    var dispatch = _ref10.dispatch,
-        getState = _ref10.getState;
+  return (_ref12) => {
+    var dispatch = _ref12.dispatch,
+        getState = _ref12.getState;
 
     if ((0, _selectors.getPause)(getState())) {
       return dispatch(command("resume"));
     }
   };
 }
 
 /**
  * Debugger breakOnNext command.
  * It's different from the comand action because we also want to
  * highlight the pause icon.
  *
  * @memberof actions/pause
  * @static
  */
 function breakOnNext() {
-  return (_ref11) => {
-    var dispatch = _ref11.dispatch,
-        client = _ref11.client;
+  return (_ref13) => {
+    var dispatch = _ref13.dispatch,
+        client = _ref13.client;
 
     client.breakOnNext();
 
     return dispatch({
       type: "BREAK_ON_NEXT",
       value: true
     });
   };
 }
 
 /**
  * @memberof actions/pause
  * @static
  */
 function selectFrame(frame) {
   return (() => {
-    var _ref12 = _asyncToGenerator(function* (_ref13) {
-      var dispatch = _ref13.dispatch,
-          client = _ref13.client;
+    var _ref14 = _asyncToGenerator(function* (_ref15) {
+      var dispatch = _ref15.dispatch,
+          client = _ref15.client;
 
       dispatch((0, _expressions.evaluateExpressions)(frame.id));
       dispatch((0, _sources.selectSource)(frame.location.sourceId, { line: frame.location.line }));
 
       var scopes = yield client.getFrameScopes(frame);
 
       dispatch({
         type: "SELECT_FRAME",
         frame,
         scopes
       });
     });
 
-    return function (_x3) {
-      return _ref12.apply(this, arguments);
+    return function (_x4) {
+      return _ref14.apply(this, arguments);
     };
   })();
 }
 
 /**
  * @memberof actions/pause
  * @static
  */
 function loadObjectProperties(object) {
-  return (_ref14) => {
-    var dispatch = _ref14.dispatch,
-        client = _ref14.client,
-        getState = _ref14.getState;
+  return (_ref16) => {
+    var dispatch = _ref16.dispatch,
+        client = _ref16.client,
+        getState = _ref16.getState;
 
     var objectId = object.actor || object.objectId;
 
-    if ((0, _selectors.getLoadedObject)(getState(), objectId)) {
+    if (!(0, _selectors.getPause)(getState()) || (0, _selectors.getLoadedObject)(getState(), objectId)) {
       return;
     }
 
     dispatch({
       type: "LOAD_OBJECT_PROPERTIES",
       objectId,
       [_promise.PROMISE]: client.getProperties(object)
     });
@@ -21606,48 +21635,43 @@ function loadObjectProperties(object) {
 /**
  * @memberOf actions/pause
  * @static
  * @param stepType
  * @returns {function(ThunkArgs)}
  */
 function astCommand(stepType) {
   return (() => {
-    var _ref15 = _asyncToGenerator(function* (_ref16) {
-      var dispatch = _ref16.dispatch,
-          getState = _ref16.getState,
-          sourceMaps = _ref16.sourceMaps;
+    var _ref17 = _asyncToGenerator(function* (_ref18) {
+      var dispatch = _ref18.dispatch,
+          getState = _ref18.getState,
+          sourceMaps = _ref18.sourceMaps;
 
       if (!_prefs.features.asyncStepping) {
         return dispatch(command(stepType));
       }
 
       var pauseInfo = (0, _selectors.getPause)(getState());
       var source = (0, _selectors.getSelectedSource)(getState()).toJS();
-      var currentHiddenBreakpointLocation = (0, _breakpoints2.getHiddenBreakpointLocation)(getState());
-
-      if (currentHiddenBreakpointLocation) {
-        dispatch((0, _breakpoints.removeBreakpoint)(currentHiddenBreakpointLocation));
-      }
 
       var pausedPosition = yield (0, _pause.getPausedPosition)(pauseInfo, sourceMaps);
 
       if (stepType == "stepOver") {
         var nextLocation = yield parser.getNextStep(source, pausedPosition);
         if (nextLocation) {
           yield dispatch((0, _breakpoints.addHiddenBreakpoint)(nextLocation));
           return dispatch(command("resume"));
         }
       }
 
       return dispatch(command(stepType));
     });
 
-    return function (_x4) {
-      return _ref15.apply(this, arguments);
+    return function (_x5) {
+      return _ref17.apply(this, arguments);
     };
   })();
 }
 
 /***/ }),
 /* 320 */
 /***/ (function(module, exports, __webpack_require__) {
 
@@ -21693,16 +21717,17 @@ function willNavigate(_, event) {
           client = _ref2.client,
           sourceMaps = _ref2.sourceMaps;
 
       yield sourceMaps.clearSourceMaps();
       (0, _wasm.clearWasmStates)();
       (0, _editor.clearDocuments)();
       (0, _parser.clearSymbols)();
       (0, _parser.clearASTs)();
+      (0, _parser.clearSources)();
 
       dispatch(navigate(event.url));
     });
 
     return function (_x) {
       return _ref.apply(this, arguments);
     };
   })();
@@ -21762,16 +21787,17 @@ exports.toggleFrameworkGrouping = toggle
 exports.setSelectedSymbolType = setSelectedSymbolType;
 exports.setFileSearchQuery = setFileSearchQuery;
 exports.updateSearchResults = updateSearchResults;
 exports.toggleFileSearchModifier = toggleFileSearchModifier;
 exports.showSource = showSource;
 exports.togglePaneCollapse = togglePaneCollapse;
 exports.highlightLineRange = highlightLineRange;
 exports.clearHighlightLineRange = clearHighlightLineRange;
+exports.toggleConditionalBreakpointPanel = toggleConditionalBreakpointPanel;
 
 var _selectors = __webpack_require__(242);
 
 var _sourceSearch = __webpack_require__(1144);
 
 function closeActiveSearch() {
   return (_ref) => {
     var getState = _ref.getState,
@@ -21892,16 +21918,23 @@ function highlightLineRange(location) {
  * @static
  */
 function clearHighlightLineRange() {
   return {
     type: "CLEAR_HIGHLIGHT_LINES"
   };
 }
 
+function toggleConditionalBreakpointPanel(line) {
+  return {
+    type: "TOGGLE_CONDITIONAL_BREAKPOINT_PANEL",
+    line
+  };
+}
+
 /***/ }),
 /* 322 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
@@ -24670,16 +24703,18 @@ var _EditorMenu = __webpack_require__(65
 var _EditorMenu2 = _interopRequireDefault(_EditorMenu);
 
 var _ConditionalPanel = __webpack_require__(711);
 
 var _devtoolsLaunchpad = __webpack_require__(131);
 
 var _source = __webpack_require__(233);
 
+var _function = __webpack_require__(1169);
+
 var _ast = __webpack_require__(1058);
 
 var _selectors = __webpack_require__(242);
 
 var _actions = __webpack_require__(244);
 
 var _actions2 = _interopRequireDefault(_actions);
 
@@ -24730,17 +24765,16 @@ var _devtoolsSourceEditor = __webpack_re
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 var cssVars = {
   searchbarHeight: "var(--editor-searchbar-height)",
   secondSearchbarHeight: "var(--editor-second-searchbar-height)",
   footerHeight: "var(--editor-footer-height)"
 };
 
-
 class Editor extends _react.PureComponent {
 
   constructor() {
     super();
 
     this.cbPanel = null;
     this.pendingJumpLocation = null;
     this.lastJumpLine = null;
@@ -24901,16 +24935,20 @@ class Editor extends _react.PureComponen
     }
 
     // Only update and jump around in real source texts. This will
     // keep the jump state around until the real source text is
     // loaded.
     if (selectedSource && selectedSource.has("text")) {
       this.highlightLine();
     }
+
+    if (this.props.conditionalBreakpointPanel !== null && this.cbPanel == null) {
+      this.toggleConditionalPanel(this.props.conditionalBreakpointPanel);
+    }
   }
 
   onToggleBreakpoint(key, e) {
     e.preventDefault();
     var codeMirror = this.state.editor.codeMirror;
     var selectedSource = this.props.selectedSource;
 
     var line = (0, _editor.getCursorLine)(codeMirror);
@@ -24988,28 +25026,30 @@ class Editor extends _react.PureComponen
 
   openMenu(event, codeMirror) {
     var _props5 = this.props,
         selectedSource = _props5.selectedSource,
         selectedLocation = _props5.selectedLocation,
         showSource = _props5.showSource,
         jumpToMappedLocation = _props5.jumpToMappedLocation,
         addExpression = _props5.addExpression,
-        toggleBlackBox = _props5.toggleBlackBox;
+        toggleBlackBox = _props5.toggleBlackBox,
+        getFunctionText = _props5.getFunctionText;
 
 
     return (0, _EditorMenu2.default)({
       codeMirror,
       event,
       selectedLocation,
       selectedSource,
       showSource,
       jumpToMappedLocation,
       addExpression,
       toggleBlackBox,
+      getFunctionText,
       onGutterContextMenu: this.onGutterContextMenu
     });
   }
 
   onGutterClick(cm, line, gutter, ev) {
     var _props6 = this.props,
         selectedSource = _props6.selectedSource,
         toggleBreakpoint = _props6.toggleBreakpoint,
@@ -25044,17 +25084,19 @@ class Editor extends _react.PureComponen
   }
 
   onGutterContextMenu(event) {
     var _props7 = this.props,
         selectedSource = _props7.selectedSource,
         breakpoints = _props7.breakpoints,
         toggleBreakpoint = _props7.toggleBreakpoint,
         toggleDisabledBreakpoint = _props7.toggleDisabledBreakpoint,
-        isEmptyLine = _props7.isEmptyLine;
+        isEmptyLine = _props7.isEmptyLine,
+        pauseData = _props7.pauseData,
+        continueToHere = _props7.continueToHere;
 
 
     if (selectedSource && selectedSource.get("isBlackBoxed")) {
       event.preventDefault();
       return;
     }
 
     var sourceId = selectedSource ? selectedSource.get("id") : "";
@@ -25066,16 +25108,18 @@ class Editor extends _react.PureComponen
     }
 
     (0, _GutterMenu2.default)({
       event,
       line,
       breakpoint,
       toggleBreakpoint,
       toggleDisabledBreakpoint,
+      pauseData,
+      continueToHere,
 
       showConditionalPanel: this.toggleConditionalPanel,
       isCbPanelOpen: this.isCbPanelOpen(),
       closeConditionalPanel: this.closeConditionalPanel
     });
   }
 
   toggleConditionalPanel(line) {
@@ -25104,16 +25148,17 @@ class Editor extends _react.PureComponen
     this.cbPanel = this.state.editor.codeMirror.addLineWidget(editorLine, panel, {
       coverGutter: true,
       noHScroll: false
     });
     this.cbPanel.node.querySelector("input").focus();
   }
 
   closeConditionalPanel() {
+    this.props.toggleConditionalBreakpointPanel(null);
     this.cbPanel.clear();
     this.cbPanel = null;
   }
 
   isCbPanelOpen() {
     return !!this.cbPanel;
   }
 
@@ -25373,17 +25418,21 @@ Editor.propTypes = {
     wholeWord: _react.PropTypes.bool.isRequired
   }).isRequired,
   startPanelSize: _react.PropTypes.number,
   endPanelSize: _react.PropTypes.number,
   linesInScope: _react.PropTypes.array,
   toggleBreakpoint: _react.PropTypes.func.isRequired,
   addOrToggleDisabledBreakpoint: _react.PropTypes.func.isRequired,
   toggleDisabledBreakpoint: _react.PropTypes.func.isRequired,
-  isEmptyLine: _react.PropTypes.func
+  conditionalBreakpointPanel: _react.PropTypes.number,
+  toggleConditionalBreakpointPanel: _react.PropTypes.func.isRequired,
+  isEmptyLine: _react.PropTypes.func,
+  continueToHere: _react.PropTypes.func,
+  getFunctionText: _react.PropTypes.func
 };
 
 Editor.contextTypes = {
   shortcuts: _react.PropTypes.object
 };
 
 exports.default = (0, _reactRedux.connect)(state => {
   var selectedLocation = (0, _selectors.getSelectedLocation)(state);
@@ -25399,17 +25448,19 @@ exports.default = (0, _reactRedux.connec
     breakpoints: (0, _selectors.getVisibleBreakpoints)(state),
     hitCount: (0, _selectors.getHitCountForSource)(state, sourceId),
     selectedFrame: (0, _selectors.getSelectedFrame)(state),
     pauseData: (0, _selectors.getPause)(state),
     coverageOn: (0, _selectors.getCoverageEnabled)(state),
     query: (0, _selectors.getFileSearchQueryState)(state),
     searchModifiers: (0, _selectors.getFileSearchModifierState)(state),
     linesInScope: (0, _selectors.getInScopeLines)(state),
-    isEmptyLine: line => (0, _ast.isEmptyLineInSource)(state, line, selectedSource.toJS())
+    getFunctionText: line => (0, _function.findFunctionText)(line, selectedSource.toJS(), (0, _selectors.getSymbols)(state, selectedSource.toJS())),
+    isEmptyLine: line => (0, _ast.isEmptyLineInSource)(state, line, selectedSource.toJS()),
+    conditionalBreakpointPanel: (0, _selectors.getConditionalBreakpointPanel)(state)
   };
 }, dispatch => (0, _redux.bindActionCreators)(_actions2.default, dispatch))(Editor);
 
 /***/ }),
 /* 427 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
@@ -26596,29 +26647,34 @@ module.exports = now;
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
+
+var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
+
 exports.default = GutterMenu;
 
 var _devtoolsLaunchpad = __webpack_require__(131);
 
 function GutterMenu(_ref) {
   var breakpoint = _ref.breakpoint,
       line = _ref.line,
       event = _ref.event,
+      pauseData = _ref.pauseData,
       toggleBreakpoint = _ref.toggleBreakpoint,
       showConditionalPanel = _ref.showConditionalPanel,
       toggleDisabledBreakpoint = _ref.toggleDisabledBreakpoint,
       isCbPanelOpen = _ref.isCbPanelOpen,
-      closeConditionalPanel = _ref.closeConditionalPanel;
+      closeConditionalPanel = _ref.closeConditionalPanel,
+      continueToHere = _ref.continueToHere;
 
   event.stopPropagation();
   event.preventDefault();
 
   var gutterItems = {
     addBreakpoint: {
       id: "node-menu-add-breakpoint",
       label: L10N.getStr("editor.addBreakpoint")
@@ -26637,16 +26693,20 @@ function GutterMenu(_ref) {
     },
     enableBreakpoint: {
       id: "node-menu-enable-breakpoint",
       label: L10N.getStr("editor.enableBreakpoint")
     },
     disableBreakpoint: {
       id: "node-menu-disable-breakpoint",
       label: L10N.getStr("editor.disableBreakpoint")
+    },
+    continueToHere: {
+      id: "node-menu-continue-to-here",
+      label: L10N.getStr("editor.continueToHere.label")
     }
   };
 
   var toggleBreakpointItem = Object.assign({
     accesskey: "B",
     disabled: false,
     click: () => {
       toggleBreakpoint(line);
@@ -26659,16 +26719,25 @@ function GutterMenu(_ref) {
   var conditionalBreakpoint = Object.assign({
     accesskey: "C",
     disabled: false,
     click: () => showConditionalPanel(line)
   }, breakpoint && breakpoint.condition ? gutterItems.editConditional : gutterItems.addConditional);
 
   var items = [toggleBreakpointItem, conditionalBreakpoint];
 
+  if (pauseData) {
+    var continueToHereItem = _extends({
+      accesskey: L10N.getStr("editor.continueToHere.accesskey"),
+      disabled: false,
+      click: () => continueToHere(line)
+    }, gutterItems.continueToHere);
+    items.push(continueToHereItem);
+  }
+
   if (breakpoint) {
     var disableBreakpoint = Object.assign({
       accesskey: "D",
       disabled: false,
       click: () => toggleDisabledBreakpoint(line)
     }, breakpoint.disabled ? gutterItems.enableBreakpoint : gutterItems.disableBreakpoint);
     items.push(disableBreakpoint);
   }
@@ -26719,20 +26788,23 @@ function _asyncToGenerator(fn) { return 
 function getMenuItems(event, _ref) {
   var codeMirror = _ref.codeMirror,
       selectedLocation = _ref.selectedLocation,
       selectedSource = _ref.selectedSource,
       showSource = _ref.showSource,
       onGutterContextMenu = _ref.onGutterContextMenu,
       jumpToMappedLocation = _ref.jumpToMappedLocation,
       toggleBlackBox = _ref.toggleBlackBox,
-      addExpression = _ref.addExpression;
+      addExpression = _ref.addExpression,
+      getFunctionText = _ref.getFunctionText;
 
   var copySourceLabel = L10N.getStr("copySource");
   var copySourceKey = L10N.getStr("copySource.accesskey");
+  var copyFunctionLabel = L10N.getStr("copyFunction.label");
+  var copyFunctionKey = L10N.getStr("copyFunction.accesskey");
   var copySourceUrlLabel = L10N.getStr("copySourceUrl");
   var copySourceUrlKey = L10N.getStr("copySourceUrl.accesskey");
   var revealInTreeLabel = L10N.getStr("sourceTabs.revealInTree");
   var revealInTreeKey = L10N.getStr("sourceTabs.revealInTree.accesskey");
   var blackboxLabel = L10N.getStr("sourceFooter.blackbox");
   var unblackboxLabel = L10N.getStr("sourceFooter.unblackbox");
   var blackboxKey = L10N.getStr("sourceFooter.blackbox.accesskey");
   var toggleBlackBoxLabel = selectedSource.get("isBlackBoxed") ? unblackboxLabel : blackboxLabel;
@@ -26796,17 +26868,26 @@ function getMenuItems(event, _ref) {
   var showSourceMenuItem = {
     id: "node-menu-show-source",
     label: revealInTreeLabel,
     accesskey: revealInTreeKey,
     disabled: false,
     click: () => showSource(selectedSource.get("id"))
   };
 
-  var menuItems = [copySource, copySourceUrl, jumpLabel, showSourceMenuItem, blackBoxMenuItem];
+  var functionText = getFunctionText(line + 1);
+  var copyFunction = {
+    id: "node-menu-copy-function",
+    label: copyFunctionLabel,
+    accesskey: copyFunctionKey,
+    disabled: !functionText,
+    click: () => (0, _clipboard.copyToTheClipboard)(functionText)
+  };
+
+  var menuItems = [copySourceUrl, jumpLabel, showSourceMenuItem, blackBoxMenuItem, copySource, copyFunction];
 
   if (textSelected) {
     menuItems.push(watchExpressionLabel);
   }
 
   return menuItems;
 }
 
@@ -28028,40 +28109,46 @@ class Breakpoints extends _react.PureCom
   showContextMenu(e, breakpoint) {
     var _props = this.props,
         removeBreakpoint = _props.removeBreakpoint,
         removeBreakpoints = _props.removeBreakpoints,
         removeAllBreakpoints = _props.removeAllBreakpoints,
         toggleBreakpoints = _props.toggleBreakpoints,
         toggleAllBreakpoints = _props.toggleAllBreakpoints,
         toggleDisabledBreakpoint = _props.toggleDisabledBreakpoint,
+        setBreakpointCondition = _props.setBreakpointCondition,
+        toggleConditionalBreakpointPanel = _props.toggleConditionalBreakpointPanel,
         breakpoints = _props.breakpoints;
 
 
     e.preventDefault();
 
     var deleteSelfLabel = L10N.getStr("breakpointMenuItem.deleteSelf");
     var deleteAllLabel = L10N.getStr("breakpointMenuItem.deleteAll");
     var deleteOthersLabel = L10N.getStr("breakpointMenuItem.deleteOthers");
     var enableSelfLabel = L10N.getStr("breakpointMenuItem.enableSelf");
     var enableAllLabel = L10N.getStr("breakpointMenuItem.enableAll");
     var enableOthersLabel = L10N.getStr("breakpointMenuItem.enableOthers");
     var disableSelfLabel = L10N.getStr("breakpointMenuItem.disableSelf");
     var disableAllLabel = L10N.getStr("breakpointMenuItem.disableAll");
     var disableOthersLabel = L10N.getStr("breakpointMenuItem.disableOthers");
+    var removeConditionLabel = L10N.getStr("breakpointMenuItem.removeCondition.label");
+    var editConditionLabel = L10N.getStr("breakpointMenuItem.editCondition.label");
 
     var deleteSelfKey = L10N.getStr("breakpointMenuItem.deleteSelf.accesskey");
     var deleteAllKey = L10N.getStr("breakpointMenuItem.deleteAll.accesskey");
     var deleteOthersKey = L10N.getStr("breakpointMenuItem.deleteOthers.accesskey");
     var enableSelfKey = L10N.getStr("breakpointMenuItem.enableSelf.accesskey");
     var enableAllKey = L10N.getStr("breakpointMenuItem.enableAll.accesskey");
     var enableOthersKey = L10N.getStr("breakpointMenuItem.enableOthers.accesskey");
     var disableSelfKey = L10N.getStr("breakpointMenuItem.disableSelf.accesskey");
     var disableAllKey = L10N.getStr("breakpointMenuItem.disableAll.accesskey");
     var disableOthersKey = L10N.getStr("breakpointMenuItem.disableOthers.accesskey");
+    var removeConditionKey = L10N.getStr("breakpointMenuItem.removeCondition.accesskey");
+    var editConditionKey = L10N.getStr("breakpointMenuItem.editCondition.accesskey");
 
     var otherBreakpoints = breakpoints.filter(b => b !== breakpoint);
     var enabledBreakpoints = breakpoints.filter(b => !b.disabled);
     var disabledBreakpoints = breakpoints.filter(b => b.disabled);
     var otherEnabledBreakpoints = breakpoints.filter(b => !b.disabled && b !== breakpoint);
     var otherDisabledBreakpoints = breakpoints.filter(b => b.disabled && b !== breakpoint);
 
     var deleteSelf = {
@@ -28130,44 +28217,69 @@ class Breakpoints extends _react.PureCom
 
     var disableOthers = {
       id: "node-menu-disable-others",
       label: disableOthersLabel,
       accesskey: disableOthersKey,
       click: () => toggleBreakpoints(true, otherEnabledBreakpoints)
     };
 
+    var removeCondition = {
+      id: "node-menu-remove-condition",
+      label: removeConditionLabel,
+      accesskey: removeConditionKey,
+      disabled: false,
+      click: () => setBreakpointCondition(breakpoint.location)
+    };
+
+    var editCondition = {
+      id: "node-menu-edit-condition",
+      label: editConditionLabel,
+      accesskey: editConditionKey,
+      click: () => toggleConditionalBreakpointPanel(breakpoint.location.line)
+    };
+
     var items = [{ item: enableSelf, hidden: () => !breakpoint.disabled }, { item: disableSelf, hidden: () => breakpoint.disabled }, { item: deleteSelf }, { item: deleteAll }, { item: deleteOthers, hidden: () => breakpoints.size === 1 }, {
       item: enableAll,
       hidden: () => disabledBreakpoints.size === 0
     }, {
       item: disableAll,
       hidden: () => enabledBreakpoints.size === 0
     }, {
       item: enableOthers,
       hidden: () => otherDisabledBreakpoints.size === 0
     }, {
       item: disableOthers,
       hidden: () => otherEnabledBreakpoints.size === 0
+    }, {
+      item: removeCondition,
+      hidden: () => !breakpoint.condition
+    }, {
+      item: editCondition,
+      hidden: () => !breakpoint.condition
     }];
 
     (0, _devtoolsLaunchpad.showMenu)(e, (0, _devtoolsLaunchpad.buildMenu)(items));
   }
 
   selectBreakpoint(breakpoint) {
     var sourceId = breakpoint.location.sourceId;
     var line = breakpoint.location.line;
     this.props.selectSource(sourceId, { line });
   }
 
   removeBreakpoint(event, breakpoint) {
     event.stopPropagation();
     this.props.removeBreakpoint(breakpoint.location);
   }
 
+  toggleConditionalBreakpointPanel(line) {
+    this.props.toggleConditionalBreakpointPanel(line);
+  }
+
   renderBreakpoint(breakpoint) {
     var snippet = breakpoint.text || "";
     var locationId = breakpoint.locationId;
     var line = breakpoint.location.line;
     var column = breakpoint.location.column;
     var isCurrentlyPaused = breakpoint.isCurrentlyPaused;
     var isDisabled = breakpoint.disabled;
     var isConditional = !!breakpoint.condition;
@@ -29317,64 +29429,54 @@ class WelcomeBox extends _react.Componen
       handleClick: togglePaneCollapse
     });
   }
 
   render() {
     var searchSourcesShortcut = (0, _text.formatKeyShortcut)(L10N.getStr("sources.search.key2"));
 
     var searchProjectShortcut = (0, _text.formatKeyShortcut)(L10N.getStr("projectTextSearch.key"));
-    var searchFunctionsShortcut = (0, _text.formatKeyShortcut)(L10N.getStr("functionSearch.key"));
 
     var searchSourcesLabel = L10N.getStr("welcome.search").substring(2);
     var searchProjectLabel = L10N.getStr("welcome.findInFiles").substring(2);
-    var searchFunctionLabel = L10N.getStr("welcome.searchFunction").substring(2);
+    var setActiveSearch = this.props.setActiveSearch;
+
 
     return _react2.default.createElement(
       "div",
       { className: "welcomebox" },
       _react2.default.createElement(
         "div",
         { className: "alignlabel" },
         _react2.default.createElement(
           "div",
           { className: "shortcutKeys" },
           _react2.default.createElement(
             "p",
-            null,
+            { onClick: setActiveSearch.bind(null, "source") },
             searchSourcesShortcut
           ),
           _react2.default.createElement(
             "p",
-            null,
+            { onClick: setActiveSearch.bind(null, "project") },
             searchProjectShortcut
-          ),
-          _react2.default.createElement(
-            "p",
-            null,
-            searchFunctionsShortcut
           )
         ),
         _react2.default.createElement(
           "div",
           { className: "shortcutFunction" },
           _react2.default.createElement(
             "p",
-            null,
+            { onClick: setActiveSearch.bind(null, "source") },
             searchSourcesLabel
           ),
           _react2.default.createElement(
             "p",
-            null,
+            { onClick: setActiveSearch.bind(null, "project") },
             searchProjectLabel
-          ),
-          _react2.default.createElement(
-            "p",
-            null,
-            searchFunctionLabel
           )
         ),
         this.renderToggleButton()
       )
     );
   }
 }
 
@@ -30145,28 +30247,35 @@ function sortTree(tree) {
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.getGeneratedLocation = undefined;
 
-var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
-
 var getGeneratedLocation = exports.getGeneratedLocation = (() => {
   var _ref = _asyncToGenerator(function* (state, source, location, sourceMaps) {
     if (!sourceMaps.isOriginalId(location.sourceId)) {
       return location;
     }
 
-    var generatedLocation = yield sourceMaps.getGeneratedLocation(location, source);
-    var generatedSource = (0, _selectors.getSource)(state, generatedLocation.sourceId);
+    var _ref2 = yield sourceMaps.getGeneratedLocation(location, source),
+        line = _ref2.line,
+        sourceId = _ref2.sourceId,
+        column = _ref2.column;
+
+    var generatedSource = (0, _selectors.getSource)(state, sourceId);
     var sourceUrl = generatedSource.get("url");
-    return _extends({}, generatedLocation, { sourceUrl });
+    return {
+      line,
+      sourceId,
+      column: column === 0 ? undefined : column,
+      sourceUrl
+    };
   });
 
   return function getGeneratedLocation(_x, _x2, _x3, _x4) {
     return _ref.apply(this, arguments);
   };
 })();
 
 var _selectors = __webpack_require__(242);
@@ -30303,16 +30412,18 @@ var findScopeByName = exports.findScopeB
     });
   });
 
   return function findScopeByName(_x3, _x4) {
     return _ref2.apply(this, arguments);
   };
 })();
 
+exports.findClosestScope = findClosestScope;
+
 var _parser = __webpack_require__(827);
 
 var _contains = __webpack_require__(1127);
 
 function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
 
 function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
 
@@ -30760,17 +30871,17 @@ exports.default = (0, _reactRedux.connec
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
-exports.getEmptyLines = exports.getNextStep = exports.clearASTs = exports.clearSymbols = exports.getOutOfScopeLocations = exports.getVariablesInScope = exports.getSymbols = exports.getClosestExpression = exports.stopParserWorker = exports.startParserWorker = undefined;
+exports.clearSources = exports.setSource = exports.hasSource = exports.getEmptyLines = exports.getNextStep = exports.clearASTs = exports.clearSymbols = exports.getOutOfScopeLocations = exports.getVariablesInScope = exports.getSymbols = exports.getClosestExpression = exports.stopParserWorker = exports.startParserWorker = undefined;
 
 var _devtoolsUtils = __webpack_require__(900);
 
 var WorkerDispatcher = _devtoolsUtils.workerUtils.WorkerDispatcher;
 
 
 var dispatcher = new WorkerDispatcher();
 var startParserWorker = exports.startParserWorker = dispatcher.start.bind(dispatcher);
@@ -30779,16 +30890,19 @@ var stopParserWorker = exports.stopParse
 var getClosestExpression = exports.getClosestExpression = dispatcher.task("getClosestExpression");
 var getSymbols = exports.getSymbols = dispatcher.task("getSymbols");
 var getVariablesInScope = exports.getVariablesInScope = dispatcher.task("getVariablesInScope");
 var getOutOfScopeLocations = exports.getOutOfScopeLocations = dispatcher.task("getOutOfScopeLocations");
 var clearSymbols = exports.clearSymbols = dispatcher.task("clearSymbols");
 var clearASTs = exports.clearASTs = dispatcher.task("clearASTs");
 var getNextStep = exports.getNextStep = dispatcher.task("getNextStep");
 var getEmptyLines = exports.getEmptyLines = dispatcher.task("getEmptyLines");
+var hasSource = exports.hasSource = dispatcher.task("hasSource");
+var setSource = exports.setSource = dispatcher.task("setSource");
+var clearSources = exports.clearSources = dispatcher.task("clearSources");
 
 /***/ }),
 /* 828 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
@@ -32039,17 +32153,18 @@ var onConnect = (() => {
       return {
         store,
         actions,
         selectors,
         client: client.clientCommands,
         prefs: _prefs.prefs,
         features: _prefs.features,
         connection,
-        bpClients
+        bpClients,
+        services
       };
     };
 
     if (!(0, _devtoolsConfig.isFirefoxPanel)()) {
       console.group("Development Notes");
       var baseUrl = "https://devtools-html.github.io/debugger.html";
       var localDevelopmentUrl = `${baseUrl}/docs/local-development.html`;
       console.log("Debugging Tips", localDevelopmentUrl);
@@ -32121,17 +32236,17 @@ var onConnect = exports.onConnect = (() 
         threadClient = _connection$tabConnec.threadClient,
         debuggerClient = _connection$tabConnec.debuggerClient;
 
 
     if (!tabTarget || !threadClient || !debuggerClient) {
       return { bpClients: {} };
     }
 
-    var supportsWasm = (0, _devtoolsConfig.isEnabled)("wasm") && !!debuggerClient.mainRoot.traits.wasmBinarySource;
+    var supportsWasm = _prefs.features.wasm && !!debuggerClient.mainRoot.traits.wasmBinarySource;
 
     var _setupCommands = (0, _commands.setupCommands)({
       threadClient,
       tabTarget,
       debuggerClient,
       supportsWasm
     }),
         bpClients = _setupCommands.bpClients;
@@ -32172,17 +32287,17 @@ var onConnect = exports.onConnect = (() 
     return _ref.apply(this, arguments);
   };
 })();
 
 var _commands = __webpack_require__(890);
 
 var _events = __webpack_require__(892);
 
-var _devtoolsConfig = __webpack_require__(828);
+var _prefs = __webpack_require__(226);
 
 function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
 
 exports.clientCommands = _commands.clientCommands;
 exports.clientEvents = _events.clientEvents;
 
 /***/ }),
 /* 890 */
@@ -32682,16 +32797,17 @@ var onConnect = exports.onConnect = (() 
 
     Debugger.scriptParsed(_events.clientEvents.scriptParsed);
     Debugger.scriptFailedToParse(_events.clientEvents.scriptFailedToParse);
     Debugger.paused(_events.clientEvents.paused);
     Debugger.resumed(_events.clientEvents.resumed);
 
     (0, _commands.setupCommands)({ Debugger, Runtime, Page });
     (0, _events.setupEvents)({ actions, Page, type, Runtime });
+    return {};
   });
 
   return function onConnect(_x, _x2) {
     return _ref.apply(this, arguments);
   };
 })();
 
 var _commands = __webpack_require__(894);
@@ -33171,17 +33287,17 @@ function updatePrefs(state) {
 
 const {
   originalToGeneratedId,
   generatedToOriginalId,
   isGeneratedId,
   isOriginalId
 } = __webpack_require__(899);
 
-const { workerUtils: { WorkerDispatcher } } = __webpack_require__(900);
+const { workerUtils: { WorkerDispatcher } } = __webpack_require__(1165);
 
 const dispatcher = new WorkerDispatcher();
 
 const getOriginalURLs = dispatcher.task("getOriginalURLs");
 const getGeneratedLocation = dispatcher.task("getGeneratedLocation");
 const getOriginalLocation = dispatcher.task("getOriginalLocation");
 const getOriginalSourceText = dispatcher.task("getOriginalSourceText");
 const applySourceMap = dispatcher.task("applySourceMap");
@@ -33357,16 +33473,20 @@ WorkerDispatcher.prototype = {
         const id = this.msgId++;
         this.worker.postMessage({ id, method, args });
 
         const listener = ({ data: result }) => {
           if (result.id !== id) {
             return;
           }
 
+          if (!this.worker) {
+            reject("Oops, The worker has shutdown!");
+            return;
+          }
           this.worker.removeEventListener("message", listener);
           if (result.error) {
             reject(result.error);
           } else {
             resolve(result.response);
           }
         };
 
@@ -33561,17 +33681,17 @@ function updatePreview(target, editor, _
     }
 
     // We are mousing over a new token that is not in the preview
     if (!target.classList.contains("debug-expression")) {
       clearPreview();
     }
   }
 
-  var invalidToken = tokenText === "" || tokenText.match(/[(){},.;\s]/);
+  var invalidToken = tokenText === "" || tokenText.match(/[(){}\|&%,.;=<>\+-/\*\s]/);
   var invalidTarget = target.parentElement && !target.parentElement.closest(".CodeMirror-line") || cursorPos.top == 0;
   var isUpdating = preview && preview.updating;
   var inScope = linesInScope && linesInScope.includes(location.line);
 
   if (invalidTarget || !inScope || isUpdating || invalidToken) {
     return;
   }
 
@@ -38226,17 +38346,17 @@ module.exports = {
   supportsObject,
   maxLengthMap
 };
 
 /***/ }),
 /* 960 */
 /***/ (function(module, exports) {
 
-module.exports = "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not distributed with this\n# file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\n# LOCALIZATION NOTE These strings are used inside the Debugger\n# which is available from the Web Developer sub-menu -> 'Debugger'.\n# The correct localization of this file might be to keep it in\n# English, or another language commonly spoken among web developers.\n# You want to make that choice consistent across the developer tools.\n# A good criteria is the language in which you'd find the best\n# documentation on web development on the web.\n\n# LOCALIZATION NOTE (collapsePanes): This is the tooltip for the button\n# that collapses the left and right panes in the debugger UI.\ncollapsePanes=Collapse panes\n\n# LOCALIZATION NOTE (copySource): This is the text that appears in the\n# context menu to copy the selected source of file open.\ncopySource=Copy\ncopySource.accesskey=y\n\n# LOCALIZATION NOTE (copySourceUrl): This is the text that appears in the\n# context menu to copy the source URL of file open.\ncopySourceUrl=Copy Source Url\ncopySourceUrl.accesskey=u\n\n# LOCALIZATION NOTE (copyStackTrace): This is the text that appears in the\n# context menu to copy the stack trace methods, file names and row number.\ncopyStackTrace=Copy Stack Trace\ncopyStackTrace.accesskey=c\n\n# LOCALIZATION NOTE (expandPanes): This is the tooltip for the button\n# that expands the left and right panes in the debugger UI.\nexpandPanes=Expand panes\n\n# LOCALIZATION NOTE (pauseButtonTooltip): The tooltip that is displayed for the pause\n# button when the debugger is in a running state.\npauseButtonTooltip=Pause %S\n\n# LOCALIZATION NOTE (pausePendingButtonTooltip): The tooltip that is displayed for\n# the pause button after it's been clicked but before the next JavaScript to run.\npausePendingButtonTooltip=Waiting for next execution\n\n# LOCALIZATION NOTE (resumeButtonTooltip): The label that is displayed on the pause\n# button when the debugger is in a paused state.\nresumeButtonTooltip=Resume %S\n\n# LOCALIZATION NOTE (stepOverTooltip): The label that is displayed on the\n# button that steps over a function call.\nstepOverTooltip=Step Over %S\n\n# LOCALIZATION NOTE (stepInTooltip): The label that is displayed on the\n# button that steps into a function call.\nstepInTooltip=Step In %S\n\n# LOCALIZATION NOTE (stepOutTooltip): The label that is displayed on the\n# button that steps out of a function call.\nstepOutTooltip=Step Out %S\n\n# LOCALIZATION NOTE (workersHeader): The text to display in the events\n# header.\nworkersHeader=Workers\n\n# LOCALIZATION NOTE (noWorkersText): The text to display in the workers list\n# when there are no workers.\nnoWorkersText=This page has no workers.\n\n# LOCALIZATION NOTE (noSourcesText): The text to display in the sources list\n# when there are no sources.\nnoSourcesText=This page has no sources.\n\n# LOCALIZATION NOTE (noEventListenersText): The text to display in the events tab\n# when there are no events.\nnoEventListenersText=No event listeners to display\n\n# LOCALIZATION NOTE (eventListenersHeader): The text to display in the events\n# header.\neventListenersHeader=Event Listeners\n\n# LOCALIZATION NOTE (noStackFramesText): The text to display in the call stack tab\n# when there are no stack frames.\nnoStackFramesText=No stack frames to display\n\n# LOCALIZATION NOTE (eventCheckboxTooltip): The tooltip text to display when\n# the user hovers over the checkbox used to toggle an event breakpoint.\neventCheckboxTooltip=Toggle breaking on this event\n\n# LOCALIZATION NOTE (eventOnSelector): The text to display in the events tab\n# for every event item, between the event type and event selector.\neventOnSelector=on\n\n# LOCALIZATION NOTE (eventInSource): The text to display in the events tab\n# for every event item, between the event selector and listener's owner source.\neventInSource=in\n\n# LOCALIZATION NOTE (eventNodes): The text to display in the events tab when\n# an event is listened on more than one target node.\neventNodes=%S nodes\n\n# LOCALIZATION NOTE (eventNative): The text to display in the events tab when\n# a listener is added from plugins, thus getting translated to native code.\neventNative=[native code]\n\n# LOCALIZATION NOTE (*Events): The text to display in the events tab for\n# each group of sub-level event entries.\nanimationEvents=Animation\naudioEvents=Audio\nbatteryEvents=Battery\nclipboardEvents=Clipboard\ncompositionEvents=Composition\ndeviceEvents=Device\ndisplayEvents=Display\ndragAndDropEvents=Drag and Drop\ngamepadEvents=Gamepad\nindexedDBEvents=IndexedDB\ninteractionEvents=Interaction\nkeyboardEvents=Keyboard\nmediaEvents=HTML5 Media\nmouseEvents=Mouse\nmutationEvents=Mutation\nnavigationEvents=Navigation\npointerLockEvents=Pointer Lock\nsensorEvents=Sensor\nstorageEvents=Storage\ntimeEvents=Time\ntouchEvents=Touch\notherEvents=Other\n\n# LOCALIZATION NOTE (blackboxCheckboxTooltip2): The tooltip text to display when\n# the user hovers over the checkbox used to toggle blackboxing its associated\n# source.\nblackboxCheckboxTooltip2=Toggle blackboxing\n\n# LOCALIZATION NOTE (sources.search.key2): Key shortcut to open the search for\n# searching all the source files the debugger has seen.\nsources.search.key2=CmdOrCtrl+P\n\n# LOCALIZATION NOTE (sources.search.alt.key): A second key shortcut to open the\n# search for searching all the source files the debugger has seen.\nsources.search.alt.key=CmdOrCtrl+O\n\n# LOCALIZATION NOTE (projectTextSearch.key): A key shortcut to open the\n# full project text search for searching all the files the debugger has seen.\nprojectTextSearch.key=CmdOrCtrl+Shift+F\n\n# LOCALIZATION NOTE (functionSearch.key): A key shortcut to open the\n# modal for searching functions in a file.\nfunctionSearch.key=CmdOrCtrl+Shift+O\n\n# LOCALIZATION NOTE (projectTextSearch.placeholder): A placeholder shown\n# when searching across all of the files in a project.\nprojectTextSearch.placeholder=Find in files…\n\n# LOCALIZATION NOTE (sources.noSourcesAvailable): Text shown when the debugger\n# does not have any sources.\nsources.noSourcesAvailable=This page has no sources\n\n# LOCALIZATION NOTE (sourceSearch.search.key2): Key shortcut to open the search\n# for searching within a the currently opened files in the editor\nsourceSearch.search.key2=CmdOrCtrl+F\n\n# LOCALIZATION NOTE (sourceSearch.search.placeholder): placeholder text in\n# the source search input bar\nsourceSearch.search.placeholder=Search in file…\n\n# LOCALIZATION NOTE (sourceSearch.search.again.key2): Key shortcut to highlight\n# the next occurrence of the last search triggered from a source search\nsourceSearch.search.again.key2=CmdOrCtrl+G\n\n# LOCALIZATION NOTE (sourceSearch.search.againPrev.key2): Key shortcut to highlight\n# the previous occurrence of the last search triggered from a source search\nsourceSearch.search.againPrev.key2=CmdOrCtrl+Shift+G\n\n# LOCALIZATION NOTE (sourceSearch.resultsSummary1): Shows a summary of\n# the number of matches for autocomplete\nsourceSearch.resultsSummary1=%d results\n\n# LOCALIZATION NOTE (noMatchingStringsText): The text to display in the\n# global search results when there are no matching strings after filtering.\nnoMatchingStringsText=No matches found\n\n# LOCALIZATION NOTE (emptySearchText): This is the text that appears in the\n# filter text box when it is empty and the scripts container is selected.\nemptySearchText=Search scripts (%S)\n\n# LOCALIZATION NOTE (emptyVariablesFilterText): This is the text that\n# appears in the filter text box for the variables view container.\nemptyVariablesFilterText=Filter variables\n\n# LOCALIZATION NOTE (emptyPropertiesFilterText): This is the text that\n# appears in the filter text box for the editor's variables view bubble.\nemptyPropertiesFilterText=Filter properties\n\n# LOCALIZATION NOTE (searchPanelFilter): This is the text that appears in the\n# filter panel popup for the filter scripts operation.\nsearchPanelFilter=Filter scripts (%S)\n\n# LOCALIZATION NOTE (searchPanelGlobal): This is the text that appears in the\n# filter panel popup for the global search operation.\nsearchPanelGlobal=Search in all files (%S)\n\n# LOCALIZATION NOTE (searchPanelFunction): This is the text that appears in the\n# filter panel popup for the function search operation.\nsearchPanelFunction=Search for function definition (%S)\n\n# LOCALIZATION NOTE (searchPanelToken): This is the text that appears in the\n# filter panel popup for the token search operation.\nsearchPanelToken=Find in this file (%S)\n\n# LOCALIZATION NOTE (searchPanelGoToLine): This is the text that appears in the\n# filter panel popup for the line search operation.\nsearchPanelGoToLine=Go to line (%S)\n\n# LOCALIZATION NOTE (searchPanelVariable): This is the text that appears in the\n# filter panel popup for the variables search operation.\nsearchPanelVariable=Filter variables (%S)\n\n# LOCALIZATION NOTE (breakpointMenuItem): The text for all the elements that\n# are displayed in the breakpoints menu item popup.\nbreakpointMenuItem.setConditional=Configure conditional breakpoint\nbreakpointMenuItem.enableSelf=Enable breakpoint\nbreakpointMenuItem.enableSelf.accesskey=E\nbreakpointMenuItem.disableSelf=Disable breakpoint\nbreakpointMenuItem.disableSelf.accesskey=D\nbreakpointMenuItem.deleteSelf=Remove breakpoint\nbreakpointMenuItem.deleteSelf.accesskey=R\nbreakpointMenuItem.enableOthers=Enable others\nbreakpointMenuItem.enableOthers.accesskey=o\nbreakpointMenuItem.disableOthers=Disable others\nbreakpointMenuItem.disableOthers.accesskey=s\nbreakpointMenuItem.deleteOthers=Remove others\nbreakpointMenuItem.deleteOthers.accesskey=h\nbreakpointMenuItem.enableAll=Enable all breakpoints\nbreakpointMenuItem.enableAll.accesskey=b\nbreakpointMenuItem.disableAll=Disable all breakpoints\nbreakpointMenuItem.disableAll.accesskey=k\nbreakpointMenuItem.deleteAll=Remove all breakpoints\nbreakpointMenuItem.deleteAll.accesskey=a\n\n# LOCALIZATION NOTE (breakpoints.header): Breakpoints right sidebar pane header.\nbreakpoints.header=Breakpoints\n\n# LOCALIZATION NOTE (breakpoints.none): The text that appears when there are\n# no breakpoints present\nbreakpoints.none=No Breakpoints\n\n# LOCALIZATION NOTE (breakpoints.enable): The text that may appear as a tooltip\n# when hovering over the 'disable breakpoints' switch button in right sidebar\nbreakpoints.enable=Enable Breakpoints\n\n# LOCALIZATION NOTE (breakpoints.disable): The text that may appear as a tooltip\n# when hovering over the 'disable breakpoints' switch button in right sidebar\nbreakpoints.disable=Disable Breakpoints\n\n# LOCALIZATION NOTE (breakpoints.removeBreakpointTooltip): The tooltip that is displayed\n# for remove breakpoint button in right sidebar\nbreakpoints.removeBreakpointTooltip=Remove Breakpoint\n\n# LOCALIZATION NOTE (callStack.header): Call Stack right sidebar pane header.\ncallStack.header=Call Stack\n\n# LOCALIZATION NOTE (callStack.notPaused): Call Stack right sidebar pane\n# message when not paused.\ncallStack.notPaused=Not Paused\n\n# LOCALIZATION NOTE (callStack.collapse): Call Stack right sidebar pane\n# message to hide some of the frames that are shown.\ncallStack.collapse=Collapse Rows\n\n# LOCALIZATION NOTE (callStack.expand): Call Stack right sidebar pane\n# message to show more of the frames.\ncallStack.expand=Expand Rows\n\n# LOCALIZATION NOTE (editor.searchResults): Editor Search bar message\n# for the summarizing the selected search result. e.g. 5 of 10 results.\neditor.searchResults=%d of %d results\n\n# LOCALIZATION NOTE (sourceSearch.singleResult): Copy shown when there is one result.\neditor.singleResult=1 result\n\n# LOCALIZATION NOTE (editor.noResults): Editor Search bar message\n# for when no results found.\neditor.noResults=no results\n\n# LOCALIZATION NOTE (editor.searchResults.nextResult): Editor Search bar\n# tooltip for traversing to the Next Result\neditor.searchResults.nextResult=Next Result\n\n# LOCALIZATION NOTE (editor.searchResults.prevResult): Editor Search bar\n# tooltip for traversing to the Previous Result\neditor.searchResults.prevResult=Previous Result\n\n# LOCALIZATION NOTE (editor.searchTypeToggleTitle): Search bar title for\n# toggling search type buttons(function search, variable search)\neditor.searchTypeToggleTitle=Search for:\n\n# LOCALIZATION NOTE (editor.addBreakpoint): Editor gutter context menu item\n# for adding a breakpoint on a line.\neditor.addBreakpoint=Add Breakpoint\n\n# LOCALIZATION NOTE (editor.disableBreakpoint): Editor gutter context menu item\n# for disabling a breakpoint on a line.\neditor.disableBreakpoint=Disable Breakpoint\n\n# LOCALIZATION NOTE (editor.enableBreakpoint): Editor gutter context menu item\n# for enabling a breakpoint on a line.\neditor.enableBreakpoint=Enable Breakpoint\n\n# LOCALIZATION NOTE (editor.removeBreakpoint): Editor gutter context menu item\n# for removing a breakpoint on a line.\neditor.removeBreakpoint=Remove Breakpoint\n\n# LOCALIZATION NOTE (editor.editBreakpoint): Editor gutter context menu item\n# for setting a breakpoint condition on a line.\neditor.editBreakpoint=Edit Breakpoint\n\n# LOCALIZATION NOTE (editor.addConditionalBreakpoint): Editor gutter context\n# menu item for adding a breakpoint condition on a line.\neditor.addConditionalBreakpoint=Add Conditional Breakpoint\n\n# LOCALIZATION NOTE (editor.conditionalPanel.placeholder): Placeholder text for\n# input element inside ConditionalPanel component\neditor.conditionalPanel.placeholder=This breakpoint will pause when the expression is true\n\n# LOCALIZATION NOTE (editor.conditionalPanel.placeholder): Tooltip text for\n# close button inside ConditionalPanel component\neditor.conditionalPanel.close=Cancel edit breakpoint and close\n\n# LOCALIZATION NOTE (editor.jumpToMappedLocation1): Context menu item\n# for navigating to a source mapped location\neditor.jumpToMappedLocation1=Jump to %S location\n\n# LOCALIZATION NOTE (framework.disableGrouping): This is the text that appears in the\n# context menu to disable framework grouping.\nframework.disableGrouping=Disable Framework Grouping\nframework.disableGrouping.accesskey=u\n\n# LOCALIZATION NOTE (framework.enableGrouping): This is the text that appears in the\n# context menu to enable framework grouping.\nframework.enableGrouping=Enable Framework Grouping\nframework.enableGrouping.accesskey=u\n\n# LOCALIZATION NOTE (generated): Source Map term for a server source location\ngenerated=generated\n\n# LOCALIZATION NOTE (original): Source Map term for a debugger UI source location\noriginal=original\n\n# LOCALIZATION NOTE (expressions.placeholder): Placeholder text for expression\n# input element\nexpressions.placeholder=Add Watch Expression\n\n# LOCALIZATION NOTE (sourceTabs.closeTab): Editor source tab context menu item\n# for closing the selected tab below the mouse.\nsourceTabs.closeTab=Close tab\nsourceTabs.closeTab.accesskey=c\n\n# LOCALIZATION NOTE (sourceTabs.closeOtherTabs): Editor source tab context menu item\n# for closing the other tabs.\nsourceTabs.closeOtherTabs=Close others\nsourceTabs.closeOtherTabs.accesskey=o\n\n# LOCALIZATION NOTE (sourceTabs.closeTabsToEnd): Editor source tab context menu item\n# for closing the tabs to the end (the right for LTR languages) of the selected tab.\nsourceTabs.closeTabsToEnd=Close tabs to the right\nsourceTabs.closeTabsToEnd.accesskey=e\n\n# LOCALIZATION NOTE (sourceTabs.closeAllTabs): Editor source tab context menu item\n# for closing all tabs.\nsourceTabs.closeAllTabs=Close all tabs\nsourceTabs.closeAllTabs.accesskey=a\n\n# LOCALIZATION NOTE (sourceTabs.revealInTree): Editor source tab context menu item\n# for revealing source in tree.\nsourceTabs.revealInTree=Reveal in Tree\nsourceTabs.revealInTree.accesskey=r\n\n# LOCALIZATION NOTE (sourceTabs.copyLink): Editor source tab context menu item\n# for copying a link address.\nsourceTabs.copyLink=Copy Link Address\nsourceTabs.copyLink.accesskey=l\n\n# LOCALIZATION NOTE (sourceTabs.prettyPrint): Editor source tab context menu item\n# for pretty printing the source.\nsourceTabs.prettyPrint=Pretty Print Source\nsourceTabs.prettyPrint.accesskey=p\n\n# LOCALIZATION NOTE (sourceFooter.blackbox): Tooltip text associated\n# with the blackbox button\nsourceFooter.blackbox=Blackbox Source\nsourceFooter.blackbox.accesskey=B\n\n# LOCALIZATION NOTE (sourceFooter.unblackbox): Tooltip text associated\n# with the blackbox button\nsourceFooter.unblackbox=Unblackbox Source\nsourceFooter.unblackbox.accesskey=b\n\n# LOCALIZATION NOTE (sourceFooter.blackboxed): Text associated\n# with a blackboxed source\nsourceFooter.blackboxed=Blackboxed Source\n\n# LOCALIZATION NOTE (sourceFooter.codeCoverage): Text associated\n# with a code coverage button\nsourceFooter.codeCoverage=Code Coverage\n\n# LOCALIZATION NOTE (sourceTabs.closeTabButtonTooltip): The tooltip that is displayed\n# for close tab button in source tabs.\nsourceTabs.closeTabButtonTooltip=Close tab\n\n# LOCALIZATION NOTE (sourceTabs.newTabButtonTooltip): The tooltip that is displayed for\n# new tab button in source tabs.\nsourceTabs.newTabButtonTooltip=Search for sources (%S)\n\n# LOCALIZATION NOTE (scopes.header): Scopes right sidebar pane header.\nscopes.header=Scopes\n\n# LOCALIZATION NOTE (scopes.notAvailable): Scopes right sidebar pane message\n# for when the debugger is paused, but there isn't pause data.\nscopes.notAvailable=Scopes Unavailable\n\n# LOCALIZATION NOTE (scopes.notPaused): Scopes right sidebar pane message\n# for when the debugger is not paused.\nscopes.notPaused=Not Paused\n\n# LOCALIZATION NOTE (scopes.block): Refers to a block of code in\n# the scopes pane when the debugger is paused.\nscopes.block=Block\n\n# LOCALIZATION NOTE (sources.header): Sources left sidebar header\nsources.header=Sources\n\n# LOCALIZATION NOTE (outline.header): Outline left sidebar header\noutline.header=Outline\n\n# LOCALIZATION NOTE (sources.search): Sources left sidebar prompt\n# e.g. Cmd+P to search. On a mac, we use the command unicode character.\n# On windows, it's ctrl.\nsources.search=%S to search\n\n# LOCALIZATION NOTE (watchExpressions.header): Watch Expressions right sidebar\n# pane header.\nwatchExpressions.header=Watch Expressions\n\n# LOCALIZATION NOTE (watchExpressions.refreshButton): Watch Expressions header\n# button for refreshing the expressions.\nwatchExpressions.refreshButton=Refresh\n\n# LOCALIZATION NOTE (welcome.search): The center pane welcome panel's\n# search prompt. e.g. cmd+p to search for files. On windows, it's ctrl, on\n# a mac we use the unicode character.\nwelcome.search=%S to search for sources\n\n# LOCALIZATION NOTE (welcome.findInFiles): The center pane welcome panel's\n# search prompt. e.g. cmd+f to search for files. On windows, it's ctrl+shift+f, on\n# a mac we use the unicode character.\nwelcome.findInFiles=%S to find in files\n\n# LOCALIZATION NOTE (welcome.searchFunction): Label displayed in the welcome\n# panel. %S is replaced by the keyboard shortcut to search for functions.\nwelcome.searchFunction=%S to search for functions in file\n\n# LOCALIZATION NOTE (sourceSearch.search): The center pane Source Search\n# prompt for searching for files.\nsourceSearch.search=Search sources…\n\n# LOCALIZATION NOTE (sourceSearch.noResults): The center pane Source Search\n# message when the query did not match any of the sources.\nsourceSearch.noResults2=No results found\n\n# LOCALIZATION NOTE (ignoreExceptions): The pause on exceptions button tooltip\n# when the debugger will not pause on exceptions.\nignoreExceptions=Ignore exceptions. Click to pause on uncaught exceptions\n\n# LOCALIZATION NOTE (pauseOnUncaughtExceptions): The pause on exceptions button\n# tooltip when the debugger will pause on uncaught exceptions.\npauseOnUncaughtExceptions=Pause on uncaught exceptions. Click to pause on all exceptions\n\n# LOCALIZATION NOTE (pauseOnExceptions): The pause on exceptions button tooltip\n# when the debugger will pause on all exceptions.\npauseOnExceptions=Pause on all exceptions. Click to ignore exceptions\n\n# LOCALIZATION NOTE (loadingText): The text that is displayed in the script\n# editor when the loading process has started but there is no file to display\n# yet.\nloadingText=Loading\\u2026\n\n# LOCALIZATION NOTE (errorLoadingText2): The text that is displayed in the debugger\n# viewer when there is an error loading a file\nerrorLoadingText2=Error loading this URL: %S\n\n# LOCALIZATION NOTE (addWatchExpressionText): The text that is displayed in the\n# watch expressions list to add a new item.\naddWatchExpressionText=Add watch expression\n\n# LOCALIZATION NOTE (addWatchExpressionButton): The button that is displayed in the\n# variables view popup.\naddWatchExpressionButton=Watch\n\n# LOCALIZATION NOTE (emptyVariablesText): The text that is displayed in the\n# variables pane when there are no variables to display.\nemptyVariablesText=No variables to display\n\n# LOCALIZATION NOTE (scopeLabel): The text that is displayed in the variables\n# pane as a header for each variable scope (e.g. \"Global scope, \"With scope\",\n# etc.).\nscopeLabel=%S scope\n\n# LOCALIZATION NOTE (watchExpressionsScopeLabel): The name of the watch\n# expressions scope. This text is displayed in the variables pane as a header for\n# the watch expressions scope.\nwatchExpressionsScopeLabel=Watch expressions\n\n# LOCALIZATION NOTE (globalScopeLabel): The name of the global scope. This text\n# is added to scopeLabel and displayed in the variables pane as a header for\n# the global scope.\nglobalScopeLabel=Global\n\n# LOCALIZATION NOTE (variablesViewErrorStacktrace): This is the text that is\n# shown before the stack trace in an error.\nvariablesViewErrorStacktrace=Stack trace:\n\n# LOCALIZATION NOTE (variablesViewMoreObjects): the text that is displayed\n# when you have an object preview that does not show all of the elements. At the end of the list\n# you see \"N more...\" in the web console output.\n# This is a semi-colon list of plural forms.\n# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals\n# #1 number of remaining items in the object\n# example: 3 more…\nvariablesViewMoreObjects=#1 more…;#1 more…\n\n# LOCALIZATION NOTE (variablesEditableNameTooltip): The text that is displayed\n# in the variables list on an item with an editable name.\nvariablesEditableNameTooltip=Double click to edit\n\n# LOCALIZATION NOTE (variablesEditableValueTooltip): The text that is displayed\n# in the variables list on an item with an editable value.\nvariablesEditableValueTooltip=Click to change value\n\n# LOCALIZATION NOTE (variablesCloseButtonTooltip): The text that is displayed\n# in the variables list on an item which can be removed.\nvariablesCloseButtonTooltip=Click to remove\n\n# LOCALIZATION NOTE (variablesEditButtonTooltip): The text that is displayed\n# in the variables list on a getter or setter which can be edited.\nvariablesEditButtonTooltip=Click to set value\n\n# LOCALIZATION NOTE (variablesEditableValueTooltip): The text that is displayed\n# in a tooltip on the \"open in inspector\" button in the the variables list for a\n# DOMNode item.\nvariablesDomNodeValueTooltip=Click to select the node in the inspector\n\n# LOCALIZATION NOTE (configurable|...|Tooltip): The text that is displayed\n# in the variables list on certain variables or properties as tooltips.\n# Expanations of what these represent can be found at the following links:\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/isFrozen\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/isSealed\n# It's probably best to keep these in English.\nconfigurableTooltip=configurable\nenumerableTooltip=enumerable\nwritableTooltip=writable\nfrozenTooltip=frozen\nsealedTooltip=sealed\nextensibleTooltip=extensible\noverriddenTooltip=overridden\nWebIDLTooltip=WebIDL\n\n# LOCALIZATION NOTE (variablesSeparatorLabel): The text that is displayed\n# in the variables list as a separator between the name and value.\nvariablesSeparatorLabel=:\n\n# LOCALIZATION NOTE (watchExpressionsSeparatorLabel2): The text that is displayed\n# in the watch expressions list as a separator between the code and evaluation.\nwatchExpressionsSeparatorLabel2=\\u0020→\n\n# LOCALIZATION NOTE (functionSearchSeparatorLabel): The text that is displayed\n# in the functions search panel as a separator between function's inferred name\n# and its real name (if available).\nfunctionSearchSeparatorLabel=←\n\n# LOCALIZATION NOTE(symbolSearch.search.functionsPlaceholder): The placeholder\n# text displayed when the user searches for functions in a file\nsymbolSearch.search.functionsPlaceholder=Search functions…\n\n# LOCALIZATION NOTE(symbolSearch.search.variablesPlaceholder): The placeholder\n# text displayed when the user searches for variables in a file\nsymbolSearch.search.variablesPlaceholder=Search variables…\n\n# LOCALIZATION NOTE(symbolSearch.search.key2): The Key Shortcut for\n# searching for a function or variable\nsymbolSearch.search.key2=CmdOrCtrl+Shift+O\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.modifiersLabel): A label\n# preceding the group of modifiers\nsymbolSearch.searchModifier.modifiersLabel=Modifiers:\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.regex): A search option\n# when searching text in a file\nsymbolSearch.searchModifier.regex=Regex\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.caseSensitive): A search option\n# when searching text in a file\nsymbolSearch.searchModifier.caseSensitive=Case sensitive\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.wholeWord): A search option\n# when searching text in a file\nsymbolSearch.searchModifier.wholeWord=Whole word\n\n# LOCALIZATION NOTE (resumptionOrderPanelTitle): This is the text that appears\n# as a description in the notification panel popup, when multiple debuggers are\n# open in separate tabs and the user tries to resume them in the wrong order.\n# The substitution parameter is the URL of the last paused window that must be\n# resumed first.\nresumptionOrderPanelTitle=There are one or more paused debuggers. Please resume the most-recently paused debugger first at: %S\n\nvariablesViewOptimizedOut=(optimized away)\nvariablesViewUninitialized=(uninitialized)\nvariablesViewMissingArgs=(unavailable)\n\nanonymousSourcesLabel=Anonymous Sources\n\nexperimental=This is an experimental feature\n\n# LOCALIZATION NOTE (whyPaused.debuggerStatement): The text that is displayed\n# in a info block explaining how the debugger is currently paused due to a `debugger`\n# statement in the code\nwhyPaused.debuggerStatement=Paused on debugger statement\n\n# LOCALIZATION NOTE (whyPaused.breakpoint): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a breakpoint\nwhyPaused.breakpoint=Paused on breakpoint\n\n# LOCALIZATION NOTE (whyPaused.exception): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an exception\nwhyPaused.exception=Paused on exception\n\n# LOCALIZATION NOTE (whyPaused.resumeLimit): The text that is displayed\n# in a info block explaining how the debugger is currently paused while stepping\n# in or out of the stack\nwhyPaused.resumeLimit=Paused while stepping\n\n# LOCALIZATION NOTE (whyPaused.pauseOnDOMEvents): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a\n# dom event\nwhyPaused.pauseOnDOMEvents=Paused on event listener\n\n# LOCALIZATION NOTE (whyPaused.breakpointConditionThrown): The text that is displayed\n# in an info block when evaluating a conditional breakpoint throws an error\nwhyPaused.breakpointConditionThrown=Error with conditional breakpoint\n\n# LOCALIZATION NOTE (whyPaused.xhr): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an\n# xml http request\nwhyPaused.xhr=Paused on XMLHttpRequest\n\n# LOCALIZATION NOTE (whyPaused.promiseRejection): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a\n# promise rejection\nwhyPaused.promiseRejection=Paused on promise rejection\n\n# LOCALIZATION NOTE (whyPaused.assert): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an\n# assert\nwhyPaused.assert=Paused on assertion\n\n# LOCALIZATION NOTE (whyPaused.debugCommand): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a\n# debugger statement\nwhyPaused.debugCommand=Paused on debugged function\n\n# LOCALIZATION NOTE (whyPaused.other): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an event\n# listener breakpoint set\nwhyPaused.other=Debugger paused\n\n# LOCALIZATION NOTE (ctrl): The text that is used for documenting\n# keyboard shortcuts that use the control key\nctrl=Ctrl\n"
+module.exports = "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not distributed with this\n# file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\n# LOCALIZATION NOTE These strings are used inside the Debugger\n# which is available from the Web Developer sub-menu -> 'Debugger'.\n# The correct localization of this file might be to keep it in\n# English, or another language commonly spoken among web developers.\n# You want to make that choice consistent across the developer tools.\n# A good criteria is the language in which you'd find the best\n# documentation on web development on the web.\n\n# LOCALIZATION NOTE (collapsePanes): This is the tooltip for the button\n# that collapses the left and right panes in the debugger UI.\ncollapsePanes=Collapse panes\n\n# LOCALIZATION NOTE (copySource): This is the text that appears in the\n# context menu to copy the selected source of file open.\ncopySource=Copy\ncopySource.accesskey=y\n\n# LOCALIZATION NOTE (copySourceUrl): This is the text that appears in the\n# context menu to copy the source URL of file open.\ncopySourceUrl=Copy Source URL\ncopySourceUrl.accesskey=u\n\n# LOCALIZATION NOTE (copyFunction): This is the text that appears in the\n# context menu to copy the function the user selected\ncopyFunction.label=Copy Function\ncopyFunction.accesskey=F\n\n# LOCALIZATION NOTE (copyStackTrace): This is the text that appears in the\n# context menu to copy the stack trace methods, file names and row number.\ncopyStackTrace=Copy Stack Trace\ncopyStackTrace.accesskey=c\n\n# LOCALIZATION NOTE (expandPanes): This is the tooltip for the button\n# that expands the left and right panes in the debugger UI.\nexpandPanes=Expand panes\n\n# LOCALIZATION NOTE (pauseButtonTooltip): The tooltip that is displayed for the pause\n# button when the debugger is in a running state.\npauseButtonTooltip=Pause %S\n\n# LOCALIZATION NOTE (pausePendingButtonTooltip): The tooltip that is displayed for\n# the pause button after it's been clicked but before the next JavaScript to run.\npausePendingButtonTooltip=Waiting for next execution\n\n# LOCALIZATION NOTE (resumeButtonTooltip): The label that is displayed on the pause\n# button when the debugger is in a paused state.\nresumeButtonTooltip=Resume %S\n\n# LOCALIZATION NOTE (stepOverTooltip): The label that is displayed on the\n# button that steps over a function call.\nstepOverTooltip=Step Over %S\n\n# LOCALIZATION NOTE (stepInTooltip): The label that is displayed on the\n# button that steps into a function call.\nstepInTooltip=Step In %S\n\n# LOCALIZATION NOTE (stepOutTooltip): The label that is displayed on the\n# button that steps out of a function call.\nstepOutTooltip=Step Out %S\n\n# LOCALIZATION NOTE (workersHeader): The text to display in the events\n# header.\nworkersHeader=Workers\n\n# LOCALIZATION NOTE (noWorkersText): The text to display in the workers list\n# when there are no workers.\nnoWorkersText=This page has no workers.\n\n# LOCALIZATION NOTE (noSourcesText): The text to display in the sources list\n# when there are no sources.\nnoSourcesText=This page has no sources.\n\n# LOCALIZATION NOTE (noEventListenersText): The text to display in the events tab\n# when there are no events.\nnoEventListenersText=No event listeners to display\n\n# LOCALIZATION NOTE (eventListenersHeader): The text to display in the events\n# header.\neventListenersHeader=Event Listeners\n\n# LOCALIZATION NOTE (noStackFramesText): The text to display in the call stack tab\n# when there are no stack frames.\nnoStackFramesText=No stack frames to display\n\n# LOCALIZATION NOTE (eventCheckboxTooltip): The tooltip text to display when\n# the user hovers over the checkbox used to toggle an event breakpoint.\neventCheckboxTooltip=Toggle breaking on this event\n\n# LOCALIZATION NOTE (eventOnSelector): The text to display in the events tab\n# for every event item, between the event type and event selector.\neventOnSelector=on\n\n# LOCALIZATION NOTE (eventInSource): The text to display in the events tab\n# for every event item, between the event selector and listener's owner source.\neventInSource=in\n\n# LOCALIZATION NOTE (eventNodes): The text to display in the events tab when\n# an event is listened on more than one target node.\neventNodes=%S nodes\n\n# LOCALIZATION NOTE (eventNative): The text to display in the events tab when\n# a listener is added from plugins, thus getting translated to native code.\neventNative=[native code]\n\n# LOCALIZATION NOTE (*Events): The text to display in the events tab for\n# each group of sub-level event entries.\nanimationEvents=Animation\naudioEvents=Audio\nbatteryEvents=Battery\nclipboardEvents=Clipboard\ncompositionEvents=Composition\ndeviceEvents=Device\ndisplayEvents=Display\ndragAndDropEvents=Drag and Drop\ngamepadEvents=Gamepad\nindexedDBEvents=IndexedDB\ninteractionEvents=Interaction\nkeyboardEvents=Keyboard\nmediaEvents=HTML5 Media\nmouseEvents=Mouse\nmutationEvents=Mutation\nnavigationEvents=Navigation\npointerLockEvents=Pointer Lock\nsensorEvents=Sensor\nstorageEvents=Storage\ntimeEvents=Time\ntouchEvents=Touch\notherEvents=Other\n\n# LOCALIZATION NOTE (blackboxCheckboxTooltip2): The tooltip text to display when\n# the user hovers over the checkbox used to toggle blackboxing its associated\n# source.\nblackboxCheckboxTooltip2=Toggle blackboxing\n\n# LOCALIZATION NOTE (sources.search.key2): Key shortcut to open the search for\n# searching all the source files the debugger has seen.\nsources.search.key2=CmdOrCtrl+P\n\n# LOCALIZATION NOTE (sources.search.alt.key): A second key shortcut to open the\n# search for searching all the source files the debugger has seen.\nsources.search.alt.key=CmdOrCtrl+O\n\n# LOCALIZATION NOTE (projectTextSearch.key): A key shortcut to open the\n# full project text search for searching all the files the debugger has seen.\nprojectTextSearch.key=CmdOrCtrl+Shift+F\n\n# LOCALIZATION NOTE (functionSearch.key): A key shortcut to open the\n# modal for searching functions in a file.\nfunctionSearch.key=CmdOrCtrl+Shift+O\n\n# LOCALIZATION NOTE (projectTextSearch.placeholder): A placeholder shown\n# when searching across all of the files in a project.\nprojectTextSearch.placeholder=Find in files…\n\n# LOCALIZATION NOTE (projectTextSearch.noResults): The center pane Text Search\n# message when the query did not match any text of all files in a project.\nprojectTextSearch.noResults=No results found\n\n# LOCALIZATION NOTE (sources.noSourcesAvailable): Text shown when the debugger\n# does not have any sources.\nsources.noSourcesAvailable=This page has no sources\n\n# LOCALIZATION NOTE (sourceSearch.search.key2): Key shortcut to open the search\n# for searching within a the currently opened files in the editor\nsourceSearch.search.key2=CmdOrCtrl+F\n\n# LOCALIZATION NOTE (sourceSearch.search.placeholder): placeholder text in\n# the source search input bar\nsourceSearch.search.placeholder=Search in file…\n\n# LOCALIZATION NOTE (sourceSearch.search.again.key2): Key shortcut to highlight\n# the next occurrence of the last search triggered from a source search\nsourceSearch.search.again.key2=CmdOrCtrl+G\n\n# LOCALIZATION NOTE (sourceSearch.search.againPrev.key2): Key shortcut to highlight\n# the previous occurrence of the last search triggered from a source search\nsourceSearch.search.againPrev.key2=CmdOrCtrl+Shift+G\n\n# LOCALIZATION NOTE (sourceSearch.resultsSummary1): Shows a summary of\n# the number of matches for autocomplete\nsourceSearch.resultsSummary1=%d results\n\n# LOCALIZATION NOTE (noMatchingStringsText): The text to display in the\n# global search results when there are no matching strings after filtering.\nnoMatchingStringsText=No matches found\n\n# LOCALIZATION NOTE (emptySearchText): This is the text that appears in the\n# filter text box when it is empty and the scripts container is selected.\nemptySearchText=Search scripts (%S)\n\n# LOCALIZATION NOTE (emptyVariablesFilterText): This is the text that\n# appears in the filter text box for the variables view container.\nemptyVariablesFilterText=Filter variables\n\n# LOCALIZATION NOTE (emptyPropertiesFilterText): This is the text that\n# appears in the filter text box for the editor's variables view bubble.\nemptyPropertiesFilterText=Filter properties\n\n# LOCALIZATION NOTE (searchPanelFilter): This is the text that appears in the\n# filter panel popup for the filter scripts operation.\nsearchPanelFilter=Filter scripts (%S)\n\n# LOCALIZATION NOTE (searchPanelGlobal): This is the text that appears in the\n# filter panel popup for the global search operation.\nsearchPanelGlobal=Search in all files (%S)\n\n# LOCALIZATION NOTE (searchPanelFunction): This is the text that appears in the\n# filter panel popup for the function search operation.\nsearchPanelFunction=Search for function definition (%S)\n\n# LOCALIZATION NOTE (searchPanelToken): This is the text that appears in the\n# filter panel popup for the token search operation.\nsearchPanelToken=Find in this file (%S)\n\n# LOCALIZATION NOTE (searchPanelGoToLine): This is the text that appears in the\n# filter panel popup for the line search operation.\nsearchPanelGoToLine=Go to line (%S)\n\n# LOCALIZATION NOTE (searchPanelVariable): This is the text that appears in the\n# filter panel popup for the variables search operation.\nsearchPanelVariable=Filter variables (%S)\n\n# LOCALIZATION NOTE (breakpointMenuItem): The text for all the elements that\n# are displayed in the breakpoints menu item popup.\nbreakpointMenuItem.setConditional=Configure conditional breakpoint\nbreakpointMenuItem.enableSelf=Enable breakpoint\nbreakpointMenuItem.enableSelf.accesskey=E\nbreakpointMenuItem.disableSelf=Disable breakpoint\nbreakpointMenuItem.disableSelf.accesskey=D\nbreakpointMenuItem.deleteSelf=Remove breakpoint\nbreakpointMenuItem.deleteSelf.accesskey=R\nbreakpointMenuItem.enableOthers=Enable others\nbreakpointMenuItem.enableOthers.accesskey=o\nbreakpointMenuItem.disableOthers=Disable others\nbreakpointMenuItem.disableOthers.accesskey=s\nbreakpointMenuItem.deleteOthers=Remove others\nbreakpointMenuItem.deleteOthers.accesskey=h\nbreakpointMenuItem.enableAll=Enable all breakpoints\nbreakpointMenuItem.enableAll.accesskey=b\nbreakpointMenuItem.disableAll=Disable all breakpoints\nbreakpointMenuItem.disableAll.accesskey=k\nbreakpointMenuItem.deleteAll=Remove all breakpoints\nbreakpointMenuItem.deleteAll.accesskey=a\nbreakpointMenuItem.removeCondition.label=Remove breakpoint condition\nbreakpointMenuItem.removeCondition.accesskey=c\nbreakpointMenuItem.editCondition.label=Edit breakpoint condition\nbreakpointMenuItem.editCondition.accesskey=n\n\n# LOCALIZATION NOTE (breakpoints.header): Breakpoints right sidebar pane header.\nbreakpoints.header=Breakpoints\n\n# LOCALIZATION NOTE (breakpoints.none): The text that appears when there are\n# no breakpoints present\nbreakpoints.none=No Breakpoints\n\n# LOCALIZATION NOTE (breakpoints.enable): The text that may appear as a tooltip\n# when hovering over the 'disable breakpoints' switch button in right sidebar\nbreakpoints.enable=Enable Breakpoints\n\n# LOCALIZATION NOTE (breakpoints.disable): The text that may appear as a tooltip\n# when hovering over the 'disable breakpoints' switch button in right sidebar\nbreakpoints.disable=Disable Breakpoints\n\n# LOCALIZATION NOTE (breakpoints.removeBreakpointTooltip): The tooltip that is displayed\n# for remove breakpoint button in right sidebar\nbreakpoints.removeBreakpointTooltip=Remove Breakpoint\n\n# LOCALIZATION NOTE (callStack.header): Call Stack right sidebar pane header.\ncallStack.header=Call Stack\n\n# LOCALIZATION NOTE (callStack.notPaused): Call Stack right sidebar pane\n# message when not paused.\ncallStack.notPaused=Not Paused\n\n# LOCALIZATION NOTE (callStack.collapse): Call Stack right sidebar pane\n# message to hide some of the frames that are shown.\ncallStack.collapse=Collapse Rows\n\n# LOCALIZATION NOTE (callStack.expand): Call Stack right sidebar pane\n# message to show more of the frames.\ncallStack.expand=Expand Rows\n\n# LOCALIZATION NOTE (editor.searchResults): Editor Search bar message\n# for the summarizing the selected search result. e.g. 5 of 10 results.\neditor.searchResults=%d of %d results\n\n# LOCALIZATION NOTE (sourceSearch.singleResult): Copy shown when there is one result.\neditor.singleResult=1 result\n\n# LOCALIZATION NOTE (editor.noResults): Editor Search bar message\n# for when no results found.\neditor.noResults=no results\n\n# LOCALIZATION NOTE (editor.searchResults.nextResult): Editor Search bar\n# tooltip for traversing to the Next Result\neditor.searchResults.nextResult=Next Result\n\n# LOCALIZATION NOTE (editor.searchResults.prevResult): Editor Search bar\n# tooltip for traversing to the Previous Result\neditor.searchResults.prevResult=Previous Result\n\n# LOCALIZATION NOTE (editor.searchTypeToggleTitle): Search bar title for\n# toggling search type buttons(function search, variable search)\neditor.searchTypeToggleTitle=Search for:\n\n# LOCALIZATION NOTE (editor.continueToHere.label): Editor gutter context\n# menu item for jumping to a new paused location\neditor.continueToHere.label=Continue To Here\neditor.continueToHere.accesskey=H\n\n# LOCALIZATION NOTE (editor.addBreakpoint): Editor gutter context menu item\n# for adding a breakpoint on a line.\neditor.addBreakpoint=Add Breakpoint\n\n# LOCALIZATION NOTE (editor.disableBreakpoint): Editor gutter context menu item\n# for disabling a breakpoint on a line.\neditor.disableBreakpoint=Disable Breakpoint\n\n# LOCALIZATION NOTE (editor.enableBreakpoint): Editor gutter context menu item\n# for enabling a breakpoint on a line.\neditor.enableBreakpoint=Enable Breakpoint\n\n# LOCALIZATION NOTE (editor.removeBreakpoint): Editor gutter context menu item\n# for removing a breakpoint on a line.\neditor.removeBreakpoint=Remove Breakpoint\n\n# LOCALIZATION NOTE (editor.editBreakpoint): Editor gutter context menu item\n# for setting a breakpoint condition on a line.\neditor.editBreakpoint=Edit Breakpoint\n\n# LOCALIZATION NOTE (editor.addConditionalBreakpoint): Editor gutter context\n# menu item for adding a breakpoint condition on a line.\neditor.addConditionalBreakpoint=Add Conditional Breakpoint\n\n# LOCALIZATION NOTE (editor.conditionalPanel.placeholder): Placeholder text for\n# input element inside ConditionalPanel component\neditor.conditionalPanel.placeholder=This breakpoint will pause when the expression is true\n\n# LOCALIZATION NOTE (editor.conditionalPanel.placeholder): Tooltip text for\n# close button inside ConditionalPanel component\neditor.conditionalPanel.close=Cancel edit breakpoint and close\n\n# LOCALIZATION NOTE (editor.jumpToMappedLocation1): Context menu item\n# for navigating to a source mapped location\neditor.jumpToMappedLocation1=Jump to %S Location\n\n# LOCALIZATION NOTE (framework.disableGrouping): This is the text that appears in the\n# context menu to disable framework grouping.\nframework.disableGrouping=Disable Framework Grouping\nframework.disableGrouping.accesskey=u\n\n# LOCALIZATION NOTE (framework.enableGrouping): This is the text that appears in the\n# context menu to enable framework grouping.\nframework.enableGrouping=Enable Framework Grouping\nframework.enableGrouping.accesskey=u\n\n# LOCALIZATION NOTE (generated): Source Map term for a server source location\ngenerated=Generated\n\n# LOCALIZATION NOTE (original): Source Map term for a debugger UI source location\noriginal=Original\n\n# LOCALIZATION NOTE (expressions.placeholder): Placeholder text for expression\n# input element\nexpressions.placeholder=Add Watch Expression\n\n# LOCALIZATION NOTE (sourceTabs.closeTab): Editor source tab context menu item\n# for closing the selected tab below the mouse.\nsourceTabs.closeTab=Close Tab\nsourceTabs.closeTab.accesskey=c\n\n# LOCALIZATION NOTE (sourceTabs.closeOtherTabs): Editor source tab context menu item\n# for closing the other tabs.\nsourceTabs.closeOtherTabs=Close Other Tabs\nsourceTabs.closeOtherTabs.accesskey=o\n\n# LOCALIZATION NOTE (sourceTabs.closeTabsToEnd): Editor source tab context menu item\n# for closing the tabs to the end (the right for LTR languages) of the selected tab.\nsourceTabs.closeTabsToEnd=Close Tabs to the Right\nsourceTabs.closeTabsToEnd.accesskey=e\n\n# LOCALIZATION NOTE (sourceTabs.closeAllTabs): Editor source tab context menu item\n# for closing all tabs.\nsourceTabs.closeAllTabs=Close All Tabs\nsourceTabs.closeAllTabs.accesskey=a\n\n# LOCALIZATION NOTE (sourceTabs.revealInTree): Editor source tab context menu item\n# for revealing source in tree.\nsourceTabs.revealInTree=Reveal in Tree\nsourceTabs.revealInTree.accesskey=r\n\n# LOCALIZATION NOTE (sourceTabs.copyLink): Editor source tab context menu item\n# for copying a link address.\nsourceTabs.copyLink=Copy Link Address\nsourceTabs.copyLink.accesskey=l\n\n# LOCALIZATION NOTE (sourceTabs.prettyPrint): Editor source tab context menu item\n# for pretty printing the source.\nsourceTabs.prettyPrint=Pretty Print Source\nsourceTabs.prettyPrint.accesskey=p\n\n# LOCALIZATION NOTE (sourceFooter.blackbox): Tooltip text associated\n# with the blackbox button\nsourceFooter.blackbox=Blackbox Source\nsourceFooter.blackbox.accesskey=B\n\n# LOCALIZATION NOTE (sourceFooter.unblackbox): Tooltip text associated\n# with the blackbox button\nsourceFooter.unblackbox=Unblackbox Source\nsourceFooter.unblackbox.accesskey=b\n\n# LOCALIZATION NOTE (sourceFooter.blackboxed): Text associated\n# with a blackboxed source\nsourceFooter.blackboxed=Blackboxed Source\n\n# LOCALIZATION NOTE (sourceFooter.codeCoverage): Text associated\n# with a code coverage button\nsourceFooter.codeCoverage=Code Coverage\n\n# LOCALIZATION NOTE (sourceTabs.closeTabButtonTooltip): The tooltip that is displayed\n# for close tab button in source tabs.\nsourceTabs.closeTabButtonTooltip=Close tab\n\n# LOCALIZATION NOTE (sourceTabs.newTabButtonTooltip): The tooltip that is displayed for\n# new tab button in source tabs.\nsourceTabs.newTabButtonTooltip=Search for sources (%S)\n\n# LOCALIZATION NOTE (scopes.header): Scopes right sidebar pane header.\nscopes.header=Scopes\n\n# LOCALIZATION NOTE (scopes.notAvailable): Scopes right sidebar pane message\n# for when the debugger is paused, but there isn't pause data.\nscopes.notAvailable=Scopes Unavailable\n\n# LOCALIZATION NOTE (scopes.notPaused): Scopes right sidebar pane message\n# for when the debugger is not paused.\nscopes.notPaused=Not Paused\n\n# LOCALIZATION NOTE (scopes.block): Refers to a block of code in\n# the scopes pane when the debugger is paused.\nscopes.block=Block\n\n# LOCALIZATION NOTE (sources.header): Sources left sidebar header\nsources.header=Sources\n\n# LOCALIZATION NOTE (outline.header): Outline left sidebar header\noutline.header=Outline\n\n# LOCALIZATION NOTE (outline.noFunctions): Outline text when there are no functions to display\noutline.noFunctions=No functions\n\n# LOCALIZATION NOTE (sources.search): Sources left sidebar prompt\n# e.g. Cmd+P to search. On a mac, we use the command unicode character.\n# On windows, it's ctrl.\nsources.search=%S to search\n\n# LOCALIZATION NOTE (watchExpressions.header): Watch Expressions right sidebar\n# pane header.\nwatchExpressions.header=Watch Expressions\n\n# LOCALIZATION NOTE (watchExpressions.refreshButton): Watch Expressions header\n# button for refreshing the expressions.\nwatchExpressions.refreshButton=Refresh\n\n# LOCALIZATION NOTE (welcome.search): The center pane welcome panel's\n# search prompt. e.g. cmd+p to search for files. On windows, it's ctrl, on\n# a mac we use the unicode character.\nwelcome.search=%S to search for sources\n\n# LOCALIZATION NOTE (welcome.findInFiles): The center pane welcome panel's\n# search prompt. e.g. cmd+f to search for files. On windows, it's ctrl+shift+f, on\n# a mac we use the unicode character.\nwelcome.findInFiles=%S to find in files\n\n# LOCALIZATION NOTE (welcome.searchFunction): Label displayed in the welcome\n# panel. %S is replaced by the keyboard shortcut to search for functions.\nwelcome.searchFunction=%S to search for functions in file\n\n# LOCALIZATION NOTE (sourceSearch.search): The center pane Source Search\n# prompt for searching for files.\nsourceSearch.search=Search sources…\n\n# LOCALIZATION NOTE (sourceSearch.noResults): The center pane Source Search\n# message when the query did not match any of the sources.\nsourceSearch.noResults2=No results found\n\n# LOCALIZATION NOTE (ignoreExceptions): The pause on exceptions button tooltip\n# when the debugger will not pause on exceptions.\nignoreExceptions=Ignore exceptions. Click to pause on uncaught exceptions\n\n# LOCALIZATION NOTE (pauseOnUncaughtExceptions): The pause on exceptions button\n# tooltip when the debugger will pause on uncaught exceptions.\npauseOnUncaughtExceptions=Pause on uncaught exceptions. Click to pause on all exceptions\n\n# LOCALIZATION NOTE (pauseOnExceptions): The pause on exceptions button tooltip\n# when the debugger will pause on all exceptions.\npauseOnExceptions=Pause on all exceptions. Click to ignore exceptions\n\n# LOCALIZATION NOTE (loadingText): The text that is displayed in the script\n# editor when the loading process has started but there is no file to display\n# yet.\nloadingText=Loading\\u2026\n\n# LOCALIZATION NOTE (errorLoadingText2): The text that is displayed in the debugger\n# viewer when there is an error loading a file\nerrorLoadingText2=Error loading this URL: %S\n\n# LOCALIZATION NOTE (addWatchExpressionText): The text that is displayed in the\n# watch expressions list to add a new item.\naddWatchExpressionText=Add watch expression\n\n# LOCALIZATION NOTE (addWatchExpressionButton): The button that is displayed in the\n# variables view popup.\naddWatchExpressionButton=Watch\n\n# LOCALIZATION NOTE (emptyVariablesText): The text that is displayed in the\n# variables pane when there are no variables to display.\nemptyVariablesText=No variables to display\n\n# LOCALIZATION NOTE (scopeLabel): The text that is displayed in the variables\n# pane as a header for each variable scope (e.g. \"Global scope, \"With scope\",\n# etc.).\nscopeLabel=%S scope\n\n# LOCALIZATION NOTE (watchExpressionsScopeLabel): The name of the watch\n# expressions scope. This text is displayed in the variables pane as a header for\n# the watch expressions scope.\nwatchExpressionsScopeLabel=Watch expressions\n\n# LOCALIZATION NOTE (globalScopeLabel): The name of the global scope. This text\n# is added to scopeLabel and displayed in the variables pane as a header for\n# the global scope.\nglobalScopeLabel=Global\n\n# LOCALIZATION NOTE (variablesViewErrorStacktrace): This is the text that is\n# shown before the stack trace in an error.\nvariablesViewErrorStacktrace=Stack trace:\n\n# LOCALIZATION NOTE (variablesViewMoreObjects): the text that is displayed\n# when you have an object preview that does not show all of the elements. At the end of the list\n# you see \"N more...\" in the web console output.\n# This is a semi-colon list of plural forms.\n# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals\n# #1 number of remaining items in the object\n# example: 3 more…\nvariablesViewMoreObjects=#1 more…;#1 more…\n\n# LOCALIZATION NOTE (variablesEditableNameTooltip): The text that is displayed\n# in the variables list on an item with an editable name.\nvariablesEditableNameTooltip=Double click to edit\n\n# LOCALIZATION NOTE (variablesEditableValueTooltip): The text that is displayed\n# in the variables list on an item with an editable value.\nvariablesEditableValueTooltip=Click to change value\n\n# LOCALIZATION NOTE (variablesCloseButtonTooltip): The text that is displayed\n# in the variables list on an item which can be removed.\nvariablesCloseButtonTooltip=Click to remove\n\n# LOCALIZATION NOTE (variablesEditButtonTooltip): The text that is displayed\n# in the variables list on a getter or setter which can be edited.\nvariablesEditButtonTooltip=Click to set value\n\n# LOCALIZATION NOTE (variablesEditableValueTooltip): The text that is displayed\n# in a tooltip on the \"open in inspector\" button in the the variables list for a\n# DOMNode item.\nvariablesDomNodeValueTooltip=Click to select the node in the inspector\n\n# LOCALIZATION NOTE (configurable|...|Tooltip): The text that is displayed\n# in the variables list on certain variables or properties as tooltips.\n# Expanations of what these represent can be found at the following links:\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/isFrozen\n# https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/isSealed\n# It's probably best to keep these in English.\nconfigurableTooltip=configurable\nenumerableTooltip=enumerable\nwritableTooltip=writable\nfrozenTooltip=frozen\nsealedTooltip=sealed\nextensibleTooltip=extensible\noverriddenTooltip=overridden\nWebIDLTooltip=WebIDL\n\n# LOCALIZATION NOTE (variablesSeparatorLabel): The text that is displayed\n# in the variables list as a separator between the name and value.\nvariablesSeparatorLabel=:\n\n# LOCALIZATION NOTE (watchExpressionsSeparatorLabel2): The text that is displayed\n# in the watch expressions list as a separator between the code and evaluation.\nwatchExpressionsSeparatorLabel2=\\u0020→\n\n# LOCALIZATION NOTE (functionSearchSeparatorLabel): The text that is displayed\n# in the functions search panel as a separator between function's inferred name\n# and its real name (if available).\nfunctionSearchSeparatorLabel=←\n\n# LOCALIZATION NOTE(symbolSearch.search.functionsPlaceholder): The placeholder\n# text displayed when the user searches for functions in a file\nsymbolSearch.search.functionsPlaceholder=Search functions…\n\n# LOCALIZATION NOTE(symbolSearch.search.variablesPlaceholder): The placeholder\n# text displayed when the user searches for variables in a file\nsymbolSearch.search.variablesPlaceholder=Search variables…\n\n# LOCALIZATION NOTE(symbolSearch.search.key2): The Key Shortcut for\n# searching for a function or variable\nsymbolSearch.search.key2=CmdOrCtrl+Shift+O\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.modifiersLabel): A label\n# preceding the group of modifiers\nsymbolSearch.searchModifier.modifiersLabel=Modifiers:\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.regex): A search option\n# when searching text in a file\nsymbolSearch.searchModifier.regex=Regex\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.caseSensitive): A search option\n# when searching text in a file\nsymbolSearch.searchModifier.caseSensitive=Case sensitive\n\n# LOCALIZATION NOTE(symbolSearch.searchModifier.wholeWord): A search option\n# when searching text in a file\nsymbolSearch.searchModifier.wholeWord=Whole word\n\n# LOCALIZATION NOTE (resumptionOrderPanelTitle): This is the text that appears\n# as a description in the notification panel popup, when multiple debuggers are\n# open in separate tabs and the user tries to resume them in the wrong order.\n# The substitution parameter is the URL of the last paused window that must be\n# resumed first.\nresumptionOrderPanelTitle=There are one or more paused debuggers. Please resume the most-recently paused debugger first at: %S\n\nvariablesViewOptimizedOut=(optimized away)\nvariablesViewUninitialized=(uninitialized)\nvariablesViewMissingArgs=(unavailable)\n\nanonymousSourcesLabel=Anonymous Sources\n\nexperimental=This is an experimental feature\n\n# LOCALIZATION NOTE (whyPaused.debuggerStatement): The text that is displayed\n# in a info block explaining how the debugger is currently paused due to a `debugger`\n# statement in the code\nwhyPaused.debuggerStatement=Paused on debugger statement\n\n# LOCALIZATION NOTE (whyPaused.breakpoint): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a breakpoint\nwhyPaused.breakpoint=Paused on breakpoint\n\n# LOCALIZATION NOTE (whyPaused.exception): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an exception\nwhyPaused.exception=Paused on exception\n\n# LOCALIZATION NOTE (whyPaused.resumeLimit): The text that is displayed\n# in a info block explaining how the debugger is currently paused while stepping\n# in or out of the stack\nwhyPaused.resumeLimit=Paused while stepping\n\n# LOCALIZATION NOTE (whyPaused.pauseOnDOMEvents): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a\n# dom event\nwhyPaused.pauseOnDOMEvents=Paused on event listener\n\n# LOCALIZATION NOTE (whyPaused.breakpointConditionThrown): The text that is displayed\n# in an info block when evaluating a conditional breakpoint throws an error\nwhyPaused.breakpointConditionThrown=Error with conditional breakpoint\n\n# LOCALIZATION NOTE (whyPaused.xhr): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an\n# xml http request\nwhyPaused.xhr=Paused on XMLHttpRequest\n\n# LOCALIZATION NOTE (whyPaused.promiseRejection): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a\n# promise rejection\nwhyPaused.promiseRejection=Paused on promise rejection\n\n# LOCALIZATION NOTE (whyPaused.assert): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an\n# assert\nwhyPaused.assert=Paused on assertion\n\n# LOCALIZATION NOTE (whyPaused.debugCommand): The text that is displayed\n# in a info block explaining how the debugger is currently paused on a\n# debugger statement\nwhyPaused.debugCommand=Paused on debugged function\n\n# LOCALIZATION NOTE (whyPaused.other): The text that is displayed\n# in a info block explaining how the debugger is currently paused on an event\n# listener breakpoint set\nwhyPaused.other=Debugger paused\n\n# LOCALIZATION NOTE (ctrl): The text that is used for documenting\n# keyboard shortcuts that use the control key\nctrl=Ctrl\n"
 
 /***/ }),
 /* 961 */,
 /* 962 */
 /***/ (function(module, exports) {
 
 // removed by extract-text-webpack-plugin
 
@@ -41706,32 +41826,38 @@ module.exports = "<svg viewBox=\"0 0 14 
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
-exports.findScopeByName = exports.getASTLocation = undefined;
+exports.getClosestFunction = exports.findScopeByName = exports.getASTLocation = undefined;
 
 var _astBreakpointLocation = __webpack_require__(804);
 
 Object.defineProperty(exports, "getASTLocation", {
   enumerable: true,
   get: function () {
     return _astBreakpointLocation.getASTLocation;
   }
 });
 Object.defineProperty(exports, "findScopeByName", {
   enumerable: true,
   get: function () {
     return _astBreakpointLocation.findScopeByName;
   }
 });
+Object.defineProperty(exports, "getClosestFunction", {
+  enumerable: true,
+  get: function () {
+    return _astBreakpointLocation.getClosestFunction;
+  }
+});
 exports.firstString = firstString;
 exports.locationMoved = locationMoved;
 exports.makeLocationId = makeLocationId;
 exports.makePendingLocationId = makePendingLocationId;
 exports.assertBreakpoint = assertBreakpoint;
 exports.assertPendingBreakpoint = assertPendingBreakpoint;
 exports.assertLocation = assertLocation;
 exports.assertPendingLocation = assertPendingLocation;
@@ -42237,17 +42363,17 @@ function setPreview(token, tokenPos, cur
 
           var selectedFrame = (0, _selectors.getSelectedFrame)(getState());
 
           var _ref11 = yield client.evaluate(expression, {
             frameId: selectedFrame.id
           }),
               result = _ref11.result;
 
-          if (!result) {
+          if (result === undefined) {
             return;
           }
 
           return {
             expression,
             result,
             location,
             tokenPos,
@@ -42281,18 +42407,16 @@ Object.defineProperty(exports, "__esModu
 var _react = __webpack_require__(0);
 
 var _react2 = _interopRequireDefault(_react);
 
 var _classnames = __webpack_require__(175);
 
 var _classnames2 = _interopRequireDefault(_classnames);
 
-var _lodash = __webpack_require__(2);
-
 var _Svg = __webpack_require__(344);
 
 var _Svg2 = _interopRequireDefault(_Svg);
 
 var _ManagedTree = __webpack_require__(419);
 
 var _ManagedTree2 = _interopRequireDefault(_ManagedTree);
 
@@ -42467,34 +42591,34 @@ class TextSearch extends _react.Componen
     }
 
     var renderItem = (item, depth, focused, _, expanded, _ref) => {
       var setExpanded = _ref.setExpanded;
 
       return item.filepath ? this.renderFile(item, focused, expanded, setExpanded) : this.renderMatch(item, focused);
     };
 
-    var getFocusedItem = () => {
-      if (this.focusedItem === null) {
-        return results[0] ? results[0].matches[0] : null;
-      }
-      return this.focusedItem.file || this.focusedItem.match;
-    };
-
-    return _react2.default.createElement(_ManagedTree2.default, {
-      getRoots: () => results,
-      getChildren: file => file.matches || [],
-      itemHeight: 24,
-      autoExpand: 1,
-      autoExpandDepth: 1,
-      focused: getFocusedItem(),
-      getParent: item => null,
-      getPath: getFilePath,
-      renderItem: renderItem
-    });
+    if (results.length) {
+      return _react2.default.createElement(_ManagedTree2.default, {
+        getRoots: () => results,
+        getChildren: file => file.matches || [],
+        itemHeight: 24,
+        autoExpand: 1,
+        autoExpandDepth: 1,
+        getParent: item => null,
+        getPath: getFilePath,
+        renderItem: renderItem
+      });
+    } else if (this.props.query && !results.length) {
+      return _react2.default.createElement(
+        "div",
+        { className: "no-result-msg absolute-center" },
+        L10N.getStr("projectTextSearch.noResults")
+      );
+    }
   }
 
   renderInput() {
     var resultCount = this.getResultCount();
     var summaryMsg = L10N.getFormatStr("sourceSearch.resultsSummary1", resultCount);
 
     return _react2.default.createElement(_SearchInput2.default, {
       query: this.state.inputValue,
@@ -43151,20 +43275,21 @@ function updateBreakpoint(state, action)
   var pendingBreakpoint = (0, _breakpoint.createPendingBreakpoint)(breakpoint);
 
   return state.setIn(["pendingBreakpoints", locationId], pendingBreakpoint);
 }
 
 function removeBreakpoint(state, action) {
   var breakpoint = action.breakpoint;
 
+
   var locationId = (0, _breakpoint.makePendingLocationId)(breakpoint.location);
-
-  const pendingBp = state.getIn(["pendingBreakpoints", locationId]);
-  if (!pendingBp) {
+  var pendingBp = state.getIn(["pendingBreakpoints", locationId]);
+
+  if (!pendingBp && action.status == "start") {
     return state.set("pendingBreakpoints", I.Map());
   }
 
   return state.deleteIn(["pendingBreakpoints", locationId]);
 }
 
 // Selectors
 // TODO: these functions should be moved out of the reducer
@@ -43820,18 +43945,18 @@ var _utils = __webpack_require__(234);
 var _Autocomplete = __webpack_require__(342);
 
 var _Autocomplete2 = _interopRequireDefault(_Autocomplete);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 class SourceSearch extends _react.Component {
 
-  searchResults(sourceMap) {
-    return sourceMap.valueSeq().toJS().filter(source => !(0, _source.isPretty)(source)).map(source => ({
+  searchResults(sources) {
+    return sources.valueSeq().toJS().filter(source => !(0, _source.isPretty)(source) && !(0, _source.isThirdParty)(source)).map(source => ({
       value: (0, _source.getSourcePath)(source),
       title: (0, _source.getSourcePath)(source).split("/").pop(),
       subtitle: (0, _utils.endTruncateStr)((0, _source.getSourcePath)(source), 100),
       id: source.id
     }));
   }
 
   render() {
@@ -43991,29 +44116,31 @@ class PrimaryPanes extends _react.Compon
 
   render() {
     var selectedPane = this.state.selectedPane;
     var _props = this.props,
         sources = _props.sources,
         selectSource = _props.selectSource;
 
 
+    var outlineComp = (0, _devtoolsConfig.isEnabled)("outline") ? _react2.default.createElement(_Outline2.default, {
+      selectSource: selectSource,
+      isHidden: selectedPane === "sources"
+    }) : null;
+
     return _react2.default.createElement(
       "div",
       { className: "sources-panel" },
       this.renderHeader(),
       _react2.default.createElement(_SourcesTree2.default, {
         sources: sources,
         selectSource: selectSource,
         isHidden: selectedPane === "outline"
       }),
-      _react2.default.createElement(_Outline2.default, {
-        selectSource: selectSource,
-        isHidden: selectedPane === "sources"
-      }),
+      outlineComp,
       this.renderFooter()
     );
   }
 }
 
 PrimaryPanes.displayName = "PrimaryPanes";
 
 exports.default = (0, _reactRedux.connect)(state => ({
@@ -44032,32 +44159,34 @@ Object.defineProperty(exports, "__esModu
   value: true
 });
 exports.loadSourceText = loadSourceText;
 
 var _promise = __webpack_require__(193);
 
 var _ast = __webpack_require__(1059);
 
+var _source = __webpack_require__(233);
+
 function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
 
 /**
  * @memberof actions/sources
  * @static
  */
 function loadSourceText(source) {
   return (() => {
     var _ref = _asyncToGenerator(function* (_ref2) {
       var dispatch = _ref2.dispatch,
           getState = _ref2.getState,
           client = _ref2.client,
           sourceMaps = _ref2.sourceMaps;
 
       // Fetch the source text only once.
-      if (source.text) {
+      if ((0, _source.isLoaded)(source)) {
         return Promise.resolve(source);
       }
 
       yield dispatch({
         type: "LOAD_SOURCE_TEXT",
         source: source,
         [_promise.PROMISE]: _asyncToGenerator(function* () {
           if (sourceMaps.isOriginalId(source.id)) {
@@ -44144,18 +44273,16 @@ var _classnames = __webpack_require__(17
 var _classnames2 = _interopRequireDefault(_classnames);
 
 var _actions = __webpack_require__(244);
 
 var _actions2 = _interopRequireDefault(_actions);
 
 var _selectors = __webpack_require__(242);
 
-var _devtoolsConfig = __webpack_require__(828);
-
 __webpack_require__(871);
 
 var _PreviewFunction = __webpack_require__(798);
 
 var _PreviewFunction2 = _interopRequireDefault(_PreviewFunction);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
@@ -44169,16 +44296,24 @@ class Outline extends _react.Component {
     if (!selectedSource) {
       return;
     }
     var selectedSourceId = selectedSource.get("id");
     var startLine = location.start.line;
     selectSource(selectedSourceId, { line: startLine });
   }
 
+  renderPlaceholder() {
+    return _react2.default.createElement(
+      "div",
+      { className: "outline-pane-info" },
+      L10N.getStr("outline.noFunctions")
+    );
+  }
+
   renderFunction(func) {
     var name = func.name,
         location = func.location,
         parameterNames = func.parameterNames;
 
 
     return _react2.default.createElement(
       "li",
@@ -44186,38 +44321,36 @@ class Outline extends _react.Component {
         key: `${name}:${location.start.line}:${location.start.column}`,
         className: "outline-list__element",
         onClick: () => this.selectItem(location)
       },
       _react2.default.createElement(_PreviewFunction2.default, { func: { name, parameterNames } })
     );
   }
 
-  renderFunctions() {
-    var symbols = this.props.symbols;
-
-
-    return symbols.functions.filter(func => func.name != "anonymous").map(func => this.renderFunction(func));
-  }
-
-  render() {
-    var isHidden = this.props.isHidden;
-
-    if (!(0, _devtoolsConfig.isEnabled)("outline")) {
-      return null;
-    }
+  renderFunctions(symbols) {
+    return _react2.default.createElement(
+      "ul",
+      { className: "outline-list" },
+      symbols.map(func => this.renderFunction(func))
+    );
+  }
+
+  render() {
+    var _props2 = this.props,
+        isHidden = _props2.isHidden,
+        symbols = _props2.symbols;
+
+
+    var symbolsToDisplay = symbols.functions.filter(func => func.name != "anonymous");
 
     return _react2.default.createElement(
       "div",
       { className: (0, _classnames2.default)("outline", { hidden: isHidden }) },
-      _react2.default.createElement(
-        "ul",
-        { className: "outline-list" },
-        this.renderFunctions()
-      )
+      symbolsToDisplay.length > 0 ? this.renderFunctions(symbolsToDisplay) : this.renderPlaceholder()
     );
   }
 }
 
 exports.Outline = Outline;
 Outline.displayName = "Outline";
 
 exports.default = (0, _reactRedux.connect)(state => {
@@ -45953,18 +46086,53 @@ exports.default = (0, _reactRedux.connec
 /* 1162 */
 /***/ (function(module, exports) {
 
 // removed by extract-text-webpack-plugin
 
 /***/ }),
 /* 1163 */,
 /* 1164 */,
-/* 1165 */,
-/* 1166 */,
+/* 1165 */
+/***/ (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__(1166);
+const workerUtils = __webpack_require__(1168);
+
+module.exports = {
+  networkRequest,
+  workerUtils
+};
+
+/***/ }),
+/* 1166 */
+/***/ (function(module, exports) {
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+function networkRequest(url, opts) {
+  return fetch(url, {
+    cache: opts.loadFromCache ? "default" : "no-cache"
+  }).then(res => {
+    if (res.status >= 200 && res.status < 300) {
+      return res.text().then(text => ({ content: text }));
+    }
+    return Promise.reject(`request failed with status ${res.status}`);
+  });
+}
+
+module.exports = networkRequest;
+
+/***/ }),
 /* 1167 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
@@ -46061,18 +46229,200 @@ class CallSite extends _react.Component 
     return null;
   }
 }
 
 exports.default = CallSite;
 CallSite.displayName = "CallSite";
 
 /***/ }),
-/* 1168 */,
-/* 1169 */,
+/* 1168 */
+/***/ (function(module, exports) {
+
+function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
+
+function WorkerDispatcher() {
+  this.msgId = 1;
+  this.worker = null;
+} /* 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/. */
+
+WorkerDispatcher.prototype = {
+  start(url) {
+    this.worker = new Worker(url);
+    this.worker.onerror = () => {
+      console.error(`Error in worker ${url}`);
+    };
+  },
+
+  stop() {
+    if (!this.worker) {
+      return;
+    }
+
+    this.worker.terminate();
+    this.worker = null;
+  },
+
+  task(method) {
+    return (...args) => {
+      return new Promise((resolve, reject) => {
+        const id = this.msgId++;
+        this.worker.postMessage({ id, method, args });
+
+        const listener = ({ data: result }) => {
+          if (result.id !== id) {
+            return;
+          }
+
+          this.worker.removeEventListener("message", listener);
+          if (result.error) {
+            reject(result.error);
+          } else {
+            resolve(result.response);
+          }
+        };
+
+        this.worker.addEventListener("message", listener);
+      });
+    };
+  }
+};
+
+function workerHandler(publicInterface) {
+  return function (msg) {
+    const { id, method, args } = msg.data;
+    try {
+      const response = publicInterface[method].apply(undefined, args);
+      if (response instanceof Promise) {
+        response.then(val => self.postMessage({ id, response: val }),
+        // Error can't be sent via postMessage, so be sure to
+        // convert to string.
+        err => self.postMessage({ id, error: err.toString() }));
+      } else {
+        self.postMessage({ id, response });
+      }
+    } catch (error) {
+      // Error can't be sent via postMessage, so be sure to convert to
+      // string.
+      self.postMessage({ id, error: error.toString() });
+    }
+  };
+}
+
+function streamingWorkerHandler(publicInterface, { timeout = 100 } = {}, worker = self) {
+  let streamingWorker = (() => {
+    var _ref = _asyncToGenerator(function* (id, tasks) {
+      let isWorking = true;
+
+      const intervalId = setTimeout(function () {
+        isWorking = false;
+      }, timeout);
+
+      const results = [];
+      while (tasks.length !== 0 && isWorking) {
+        const { callback, context, args } = tasks.shift();
+        const result = yield callback.call(context, args);
+        results.push(result);
+      }
+      worker.postMessage({ id, status: "pending", data: results });
+      clearInterval(intervalId);
+
+      if (tasks.length !== 0) {
+        yield streamingWorker(id, tasks);
+      }
+    });
+
+    return function streamingWorker(_x, _x2) {
+      return _ref.apply(this, arguments);
+    };
+  })();
+
+  return (() => {
+    var _ref2 = _asyncToGenerator(function* (msg) {
+      const { id, method, args } = msg.data;
+      const workerMethod = publicInterface[method];
+      if (!workerMethod) {
+        console.error(`Could not find ${method} defined in worker.`);
+      }
+      worker.postMessage({ id, status: "start" });
+
+      try {
+        const tasks = workerMethod(args);
+        yield streamingWorker(id, tasks);
+        worker.postMessage({ id, status: "done" });
+      } catch (error) {
+        worker.postMessage({ id, status: "error", error });
+      }
+    });
+
+    return function (_x3) {
+      return _ref2.apply(this, arguments);
+    };
+  })();
+}
+
+module.exports = {
+  WorkerDispatcher,
+  workerHandler,
+  streamingWorkerHandler
+};
+
+/***/ }),
+/* 1169 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.findFunctionText = findFunctionText;
+
+var _astBreakpointLocation = __webpack_require__(804);
+
+function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
+
+function getIndentation(lines) {
+  var firstLine = lines[0];
+  var secondLine = lines[1];
+  var lastLine = lines[lines.length - 1];
+
+  var _getIndentation = line => line && line.match(/^\s*/)[0].length;
+
+  var indentations = [_getIndentation(firstLine), _getIndentation(secondLine), _getIndentation(lastLine)];
+
+  return Math.max.apply(Math, indentations.concat([0]));
+}
+
+function findFunctionText(line, source, symbols) {
+  var func = (0, _astBreakpointLocation.findClosestScope)(symbols.functions, { line, column: Infinity });
+  if (!func) {
+    return null;
+  }
+
+  var _func$location = func.location,
+      start = _func$location.start,
+      end = _func$location.end;
+
+  var lines = source.text.split("\n");
+  var firstLine = lines[start.line - 1].slice(start.column);
+  var lastLine = lines[end.line - 1].slice(0, end.column);
+  var middle = lines.slice(start.line, end.line - 1);
+  var functionLines = [firstLine].concat(_toConsumableArray(middle), [lastLine]);
+
+  var indentation = getIndentation(functionLines);
+  var formattedLines = functionLines.map(_line => _line.replace(new RegExp(`^\\s{0,${indentation - 1}}`), ""));
+
+  return formattedLines.join("\n").trim();
+}
+
+/***/ }),
 /* 1170 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
@@ -46388,9 +46738,9 @@ exports.default = (0, _reactRedux.connec
 /* 1173 */,
 /* 1174 */
 /***/ (function(module, exports) {
 
 module.exports = "<svg xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:cc=\"http://creativecommons.org/ns#\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 400 400\" xml:space=\"preserve\" id=\"svg2\" version=\"1.1\"><metadata id=\"metadata8\"><rdf:RDF><cc:Work rdf:about><dc:format>image/svg+xml</dc:format><dc:type rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\"></dc></cc:Work></rdf:RDF></metadata><defs id=\"defs6\"></defs><g transform=\"matrix(1.3333333,0,0,-1.3333333,0,400)\" id=\"g10\"><g transform=\"translate(178.0626,235.0086)\" id=\"g12\"><path id=\"path14\" style=\"fill:#41b883;fill-opacity:1;fill-rule:nonzero;stroke:none\" d=\"M 0,0 -22.669,-39.264 -45.338,0 h -75.491 L -22.669,-170.017 75.491,0 Z\"></path></g><g transform=\"translate(178.0626,235.0086)\" id=\"g16\"><path id=\"path18\" style=\"fill:#34495e;fill-opacity:1;fill-rule:nonzero;stroke:none\" d=\"M 0,0 -22.669,-39.264 -45.338,0 H -81.565 L -22.669,-102.01 36.227,0 Z\"></path></g></g></svg>"
 
 /***/ })
 /******/ ]);
-});
+});
\ No newline at end of file
--- a/devtools/client/debugger/new/parser-worker.js
+++ b/devtools/client/debugger/new/parser-worker.js
@@ -28726,16 +28726,20 @@ WorkerDispatcher.prototype = {
         const id = this.msgId++;
         this.worker.postMessage({ id, method, args });
 
         const listener = ({ data: result }) => {
           if (result.id !== id) {
             return;
           }
 
+          if (!this.worker) {
+            reject("Oops, The worker has shutdown!");
+            return;
+          }
           this.worker.removeEventListener("message", listener);
           if (result.error) {
             reject(result.error);
           } else {
             resolve(result.response);
           }
         };
 
@@ -28894,16 +28898,18 @@ var _closest = __webpack_require__(1055)
 var _scopes = __webpack_require__(1049);
 
 var _getSymbols = __webpack_require__(1050);
 
 var _getSymbols2 = _interopRequireDefault(_getSymbols);
 
 var _ast = __webpack_require__(1051);
 
+var _sources = __webpack_require__(1171);
+
 var _getOutOfScopeLocations = __webpack_require__(1072);
 
 var _getOutOfScopeLocations2 = _interopRequireDefault(_getOutOfScopeLocations);
 
 var _steps = __webpack_require__(842);
 
 var _getEmptyLines = __webpack_require__(845);
 
@@ -28917,16 +28923,19 @@ var workerHandler = _devtoolsUtils.worke
 
 
 self.onmessage = workerHandler({
   getClosestExpression: _closest.getClosestExpression,
   getOutOfScopeLocations: _getOutOfScopeLocations2.default,
   getSymbols: _getSymbols2.default,
   clearSymbols: _getSymbols.clearSymbols,
   clearASTs: _ast.clearASTs,
+  hasSource: _sources.hasSource,
+  setSource: _sources.setSource,
+  clearSources: _sources.clearSources,
   getVariablesInScope: _scopes.getVariablesInScope,
   getNextStep: _steps.getNextStep,
   getEmptyLines: _getEmptyLines2.default
 });
 
 /***/ }),
 /* 962 */,
 /* 963 */
@@ -32990,11 +32999,63 @@ var isArrayLike = __webpack_require__(22
  */
 function isArrayLikeObject(value) {
   return isObjectLike(value) && isArrayLike(value);
 }
 
 module.exports = isArrayLikeObject;
 
 
+/***/ }),
+/* 1156 */,
+/* 1157 */,
+/* 1158 */,
+/* 1159 */,
+/* 1160 */,
+/* 1161 */,
+/* 1162 */,
+/* 1163 */,
+/* 1164 */,
+/* 1165 */,
+/* 1166 */,
+/* 1167 */,
+/* 1168 */,
+/* 1169 */,
+/* 1170 */,
+/* 1171 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.hasSource = hasSource;
+exports.setSource = setSource;
+exports.getSource = getSource;
+exports.clearSources = clearSources;
+
+
+var cachedSources = new Map();
+
+function hasSource(sourceId) {
+  return cachedSources.has(sourceId);
+}
+
+function setSource(source) {
+  cachedSources.set(source.id, source);
+}
+
+function getSource(sourceId) {
+  if (!cachedSources.has(sourceId)) {
+    throw new Error(`${sourceId} was not provided.`);
+  }
+  return cachedSources.get(sourceId);
+}
+
+function clearSources() {
+  cachedSources = new Map();
+}
+
 /***/ })
 /******/ ]);
 });
\ No newline at end of file
--- a/devtools/client/debugger/new/pretty-print-worker.js
+++ b/devtools/client/debugger/new/pretty-print-worker.js
@@ -7430,16 +7430,20 @@ WorkerDispatcher.prototype = {
         const id = this.msgId++;
         this.worker.postMessage({ id, method, args });
 
         const listener = ({ data: result }) => {
           if (result.id !== id) {
             return;
           }
 
+          if (!this.worker) {
+            reject("Oops, The worker has shutdown!");
+            return;
+          }
           this.worker.removeEventListener("message", listener);
           if (result.error) {
             reject(result.error);
           } else {
             resolve(result.response);
           }
         };
 
--- a/devtools/client/debugger/new/search-worker.js
+++ b/devtools/client/debugger/new/search-worker.js
@@ -421,16 +421,190 @@ function findSourceMatches(source, query
   }).filter(_matches => _matches.length > 0);
 
   matches = (_ref = []).concat.apply(_ref, _toConsumableArray(matches));
   return matches;
 }
 
 /***/ }),
 
+/***/ 1165:
+/***/ (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__(1166);
+const workerUtils = __webpack_require__(1168);
+
+module.exports = {
+  networkRequest,
+  workerUtils
+};
+
+/***/ }),
+
+/***/ 1166:
+/***/ (function(module, exports) {
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+function networkRequest(url, opts) {
+  return fetch(url, {
+    cache: opts.loadFromCache ? "default" : "no-cache"
+  }).then(res => {
+    if (res.status >= 200 && res.status < 300) {
+      return res.text().then(text => ({ content: text }));
+    }
+    return Promise.reject(`request failed with status ${res.status}`);
+  });
+}
+
+module.exports = networkRequest;
+
+/***/ }),
+
+/***/ 1168:
+/***/ (function(module, exports) {
+
+function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
+
+function WorkerDispatcher() {
+  this.msgId = 1;
+  this.worker = null;
+} /* 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/. */
+
+WorkerDispatcher.prototype = {
+  start(url) {
+    this.worker = new Worker(url);
+    this.worker.onerror = () => {
+      console.error(`Error in worker ${url}`);
+    };
+  },
+
+  stop() {
+    if (!this.worker) {
+      return;
+    }
+
+    this.worker.terminate();
+    this.worker = null;
+  },
+
+  task(method) {
+    return (...args) => {
+      return new Promise((resolve, reject) => {
+        const id = this.msgId++;
+        this.worker.postMessage({ id, method, args });
+
+        const listener = ({ data: result }) => {
+          if (result.id !== id) {
+            return;
+          }
+
+          this.worker.removeEventListener("message", listener);
+          if (result.error) {
+            reject(result.error);
+          } else {
+            resolve(result.response);
+          }
+        };
+
+        this.worker.addEventListener("message", listener);
+      });
+    };
+  }
+};
+
+function workerHandler(publicInterface) {
+  return function (msg) {
+    const { id, method, args } = msg.data;
+    try {
+      const response = publicInterface[method].apply(undefined, args);
+      if (response instanceof Promise) {
+        response.then(val => self.postMessage({ id, response: val }),
+        // Error can't be sent via postMessage, so be sure to
+        // convert to string.
+        err => self.postMessage({ id, error: err.toString() }));
+      } else {
+        self.postMessage({ id, response });
+      }
+    } catch (error) {
+      // Error can't be sent via postMessage, so be sure to convert to
+      // string.
+      self.postMessage({ id, error: error.toString() });
+    }
+  };
+}
+
+function streamingWorkerHandler(publicInterface, { timeout = 100 } = {}, worker = self) {
+  let streamingWorker = (() => {
+    var _ref = _asyncToGenerator(function* (id, tasks) {
+      let isWorking = true;
+
+      const intervalId = setTimeout(function () {
+        isWorking = false;
+      }, timeout);
+
+      const results = [];
+      while (tasks.length !== 0 && isWorking) {
+        const { callback, context, args } = tasks.shift();
+        const result = yield callback.call(context, args);
+        results.push(result);
+      }
+      worker.postMessage({ id, status: "pending", data: results });
+      clearInterval(intervalId);
+
+      if (tasks.length !== 0) {
+        yield streamingWorker(id, tasks);
+      }
+    });
+
+    return function streamingWorker(_x, _x2) {
+      return _ref.apply(this, arguments);
+    };
+  })();
+
+  return (() => {
+    var _ref2 = _asyncToGenerator(function* (msg) {
+      const { id, method, args } = msg.data;
+      const workerMethod = publicInterface[method];
+      if (!workerMethod) {
+        console.error(`Could not find ${method} defined in worker.`);
+      }
+      worker.postMessage({ id, status: "start" });
+
+      try {
+        const tasks = workerMethod(args);
+        yield streamingWorker(id, tasks);
+        worker.postMessage({ id, status: "done" });
+      } catch (error) {
+        worker.postMessage({ id, status: "error", error });
+      }
+    });
+
+    return function (_x3) {
+      return _ref2.apply(this, arguments);
+    };
+  })();
+}
+
+module.exports = {
+  WorkerDispatcher,
+  workerHandler,
+  streamingWorkerHandler
+};
+
+/***/ }),
+
 /***/ 1173:
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
@@ -689,17 +863,17 @@ module.exports = isObjectLike;
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
-exports.isLoaded = exports.getMode = exports.getSourceLineCount = exports.getSourcePath = exports.getFilenameFromURL = exports.getFilename = exports.getRawSourceURL = exports.getPrettySourceURL = exports.shouldPrettyPrint = exports.isPretty = exports.isJavaScript = undefined;
+exports.isLoaded = exports.getMode = exports.getSourceLineCount = exports.getSourcePath = exports.getFilenameFromURL = exports.getFilename = exports.getRawSourceURL = exports.getPrettySourceURL = exports.shouldPrettyPrint = exports.isThirdParty = exports.isPretty = exports.isJavaScript = undefined;
 
 var _devtoolsSourceMap = __webpack_require__(898);
 
 var _utils = __webpack_require__(234);
 
 var _path = __webpack_require__(235);
 
 var _url = __webpack_require__(334);
@@ -763,16 +937,24 @@ function isJavaScript(url) {
 /**
  * @memberof utils/source
  * @static
  */
 function isPretty(source) {
   return source.url ? /formatted$/.test(source.url) : false;
 }
 
+function isThirdParty(source) {
+  if (!source || !source.url) {
+    return false;
+  }
+
+  return !!source.url.match(/(node_modules|bower_components)/);
+}
+
 /**
  * @memberof utils/source
  * @static
  */
 function getPrettySourceURL(url) {
   if (!url) {
     url = "";
   }
@@ -912,16 +1094,17 @@ function getMode(source) {
 }
 
 function isLoaded(source) {
   return source.loadedState === "loaded";
 }
 
 exports.isJavaScript = isJavaScript;
 exports.isPretty = isPretty;
+exports.isThirdParty = isThirdParty;
 exports.shouldPrettyPrint = shouldPrettyPrint;
 exports.getPrettySourceURL = getPrettySourceURL;
 exports.getRawSourceURL = getRawSourceURL;
 exports.getFilename = getFilename;
 exports.getFilenameFromURL = getFilenameFromURL;
 exports.getSourcePath = getSourcePath;
 exports.getSourceLineCount = getSourceLineCount;
 exports.getMode = getMode;
@@ -2422,17 +2605,17 @@ module.exports = root;
 
 const {
   originalToGeneratedId,
   generatedToOriginalId,
   isGeneratedId,
   isOriginalId
 } = __webpack_require__(899);
 
-const { workerUtils: { WorkerDispatcher } } = __webpack_require__(900);
+const { workerUtils: { WorkerDispatcher } } = __webpack_require__(1165);
 
 const dispatcher = new WorkerDispatcher();
 
 const getOriginalURLs = dispatcher.task("getOriginalURLs");
 const getGeneratedLocation = dispatcher.task("getGeneratedLocation");
 const getOriginalLocation = dispatcher.task("getOriginalLocation");
 const getOriginalSourceText = dispatcher.task("getOriginalSourceText");
 const applySourceMap = dispatcher.task("applySourceMap");
@@ -2624,16 +2807,20 @@ WorkerDispatcher.prototype = {
         const id = this.msgId++;
         this.worker.postMessage({ id, method, args });
 
         const listener = ({ data: result }) => {
           if (result.id !== id) {
             return;
           }
 
+          if (!this.worker) {
+            reject("Oops, The worker has shutdown!");
+            return;
+          }
           this.worker.removeEventListener("message", listener);
           if (result.error) {
             reject(result.error);
           } else {
             resolve(result.response);
           }
         };
 
--- a/devtools/client/framework/test/browser_source_map-01.js
+++ b/devtools/client/framework/test/browser_source_map-01.js
@@ -21,17 +21,17 @@ add_task(function* () {
   const service = toolbox.sourceMapURLService;
 
   // Inject JS script
   let sourceSeen = waitForSourceLoad(toolbox, JS_URL);
   yield createScript(JS_URL);
   yield sourceSeen;
 
   let loc1 = { url: JS_URL, line: 6 };
-  let newLoc1 = yield service.originalPositionFor(loc1.url, loc1.line);
+  let newLoc1 = yield service.originalPositionFor(loc1.url, loc1.line, 4);
   checkLoc1(loc1, newLoc1);
 
   let loc2 = { url: JS_URL, line: 8, column: 3 };
   let newLoc2 = yield service.originalPositionFor(loc2.url, loc2.line, loc2.column);
   checkLoc2(loc2, newLoc2);
 
   yield toolbox.destroy();
   gBrowser.removeCurrentTab();
--- a/devtools/client/framework/test/browser_source_map-absolute.js
+++ b/devtools/client/framework/test/browser_source_map-absolute.js
@@ -17,13 +17,13 @@ add_task(function* () {
   const service = toolbox.sourceMapURLService;
 
   // Inject JS script
   let sourceSeen = waitForSourceLoad(toolbox, JS_URL);
   yield createScript(JS_URL);
   yield sourceSeen;
 
   info(`checking original location for ${JS_URL}:6`);
-  let newLoc = yield service.originalPositionFor(JS_URL, 6);
+  let newLoc = yield service.originalPositionFor(JS_URL, 6, 4);
 
   is(newLoc.sourceUrl, ORIGINAL_URL, "check mapped URL");
   is(newLoc.line, 4, "check mapped line number");
 });
--- a/devtools/client/locales/en-US/debugger.properties
+++ b/devtools/client/locales/en-US/debugger.properties
@@ -16,19 +16,24 @@ collapsePanes=Collapse panes
 
 # LOCALIZATION NOTE (copySource): This is the text that appears in the
 # context menu to copy the selected source of file open.
 copySource=Copy
 copySource.accesskey=y
 
 # LOCALIZATION NOTE (copySourceUrl): This is the text that appears in the
 # context menu to copy the source URL of file open.
-copySourceUrl=Copy Source Url
+copySourceUrl=Copy Source URL
 copySourceUrl.accesskey=u
 
+# LOCALIZATION NOTE (copyFunction): This is the text that appears in the
+# context menu to copy the function the user selected
+copyFunction.label=Copy Function
+copyFunction.accesskey=F
+
 # LOCALIZATION NOTE (copyStackTrace): This is the text that appears in the
 # context menu to copy the stack trace methods, file names and row number.
 copyStackTrace=Copy Stack Trace
 copyStackTrace.accesskey=c
 
 # LOCALIZATION NOTE (expandPanes): This is the tooltip for the button
 # that expands the left and right panes in the debugger UI.
 expandPanes=Expand panes
@@ -146,16 +151,20 @@ projectTextSearch.key=CmdOrCtrl+Shift+F
 # LOCALIZATION NOTE (functionSearch.key): A key shortcut to open the
 # modal for searching functions in a file.
 functionSearch.key=CmdOrCtrl+Shift+O
 
 # LOCALIZATION NOTE (projectTextSearch.placeholder): A placeholder shown
 # when searching across all of the files in a project.
 projectTextSearch.placeholder=Find in files…
 
+# LOCALIZATION NOTE (projectTextSearch.noResults): The center pane Text Search
+# message when the query did not match any text of all files in a project.
+projectTextSearch.noResults=No results found
+
 # LOCALIZATION NOTE (sources.noSourcesAvailable): Text shown when the debugger
 # does not have any sources.
 sources.noSourcesAvailable=This page has no sources
 
 # LOCALIZATION NOTE (sourceSearch.search.key2): Key shortcut to open the search
 # for searching within a the currently opened files in the editor
 sourceSearch.search.key2=CmdOrCtrl+F
 
@@ -231,16 +240,20 @@ breakpointMenuItem.disableOthers.accessk
 breakpointMenuItem.deleteOthers=Remove others
 breakpointMenuItem.deleteOthers.accesskey=h
 breakpointMenuItem.enableAll=Enable all breakpoints
 breakpointMenuItem.enableAll.accesskey=b
 breakpointMenuItem.disableAll=Disable all breakpoints
 breakpointMenuItem.disableAll.accesskey=k
 breakpointMenuItem.deleteAll=Remove all breakpoints
 breakpointMenuItem.deleteAll.accesskey=a
+breakpointMenuItem.removeCondition.label=Remove breakpoint condition
+breakpointMenuItem.removeCondition.accesskey=c
+breakpointMenuItem.editCondition.label=Edit breakpoint condition
+breakpointMenuItem.editCondition.accesskey=n
 
 # LOCALIZATION NOTE (breakpoints.header): Breakpoints right sidebar pane header.
 breakpoints.header=Breakpoints
 
 # LOCALIZATION NOTE (breakpoints.none): The text that appears when there are
 # no breakpoints present
 breakpoints.none=No Breakpoints
 
@@ -289,16 +302,21 @@ editor.searchResults.nextResult=Next Res
 # LOCALIZATION NOTE (editor.searchResults.prevResult): Editor Search bar
 # tooltip for traversing to the Previous Result
 editor.searchResults.prevResult=Previous Result
 
 # LOCALIZATION NOTE (editor.searchTypeToggleTitle): Search bar title for
 # toggling search type buttons(function search, variable search)
 editor.searchTypeToggleTitle=Search for:
 
+# LOCALIZATION NOTE (editor.continueToHere.label): Editor gutter context
+# menu item for jumping to a new paused location
+editor.continueToHere.label=Continue To Here
+editor.continueToHere.accesskey=H
+
 # LOCALIZATION NOTE (editor.addBreakpoint): Editor gutter context menu item
 # for adding a breakpoint on a line.
 editor.addBreakpoint=Add Breakpoint
 
 # LOCALIZATION NOTE (editor.disableBreakpoint): Editor gutter context menu item
 # for disabling a breakpoint on a line.
 editor.disableBreakpoint=Disable Breakpoint
 
@@ -323,56 +341,56 @@ editor.addConditionalBreakpoint=Add Cond
 editor.conditionalPanel.placeholder=This breakpoint will pause when the expression is true
 
 # LOCALIZATION NOTE (editor.conditionalPanel.placeholder): Tooltip text for
 # close button inside ConditionalPanel component
 editor.conditionalPanel.close=Cancel edit breakpoint and close
 
 # LOCALIZATION NOTE (editor.jumpToMappedLocation1): Context menu item
 # for navigating to a source mapped location
-editor.jumpToMappedLocation1=Jump to %S location
+editor.jumpToMappedLocation1=Jump to %S Location
 
 # LOCALIZATION NOTE (framework.disableGrouping): This is the text that appears in the
 # context menu to disable framework grouping.
 framework.disableGrouping=Disable Framework Grouping
 framework.disableGrouping.accesskey=u
 
 # LOCALIZATION NOTE (framework.enableGrouping): This is the text that appears in the
 # context menu to enable framework grouping.
 framework.enableGrouping=Enable Framework Grouping
 framework.enableGrouping.accesskey=u
 
 # LOCALIZATION NOTE (generated): Source Map term for a server source location
-generated=generated
+generated=Generated
 
 # LOCALIZATION NOTE (original): Source Map term for a debugger UI source location
-original=original
+original=Original
 
 # LOCALIZATION NOTE (expressions.placeholder): Placeholder text for expression
 # input element
 expressions.placeholder=Add Watch Expression
 
 # LOCALIZATION NOTE (sourceTabs.closeTab): Editor source tab context menu item
 # for closing the selected tab below the mouse.
-sourceTabs.closeTab=Close tab
+sourceTabs.closeTab=Close Tab
 sourceTabs.closeTab.accesskey=c
 
 # LOCALIZATION NOTE (sourceTabs.closeOtherTabs): Editor source tab context menu item
 # for closing the other tabs.
-sourceTabs.closeOtherTabs=Close others
+sourceTabs.closeOtherTabs=Close Other Tabs
 sourceTabs.closeOtherTabs.accesskey=o
 
 # LOCALIZATION NOTE (sourceTabs.closeTabsToEnd): Editor source tab context menu item
 # for closing the tabs to the end (the right for LTR languages) of the selected tab.
-sourceTabs.closeTabsToEnd=Close tabs to the right
+sourceTabs.closeTabsToEnd=Close Tabs to the Right
 sourceTabs.closeTabsToEnd.accesskey=e
 
 # LOCALIZATION NOTE (sourceTabs.closeAllTabs): Editor source tab context menu item
 # for closing all tabs.
-sourceTabs.closeAllTabs=Close all tabs
+sourceTabs.closeAllTabs=Close All Tabs
 sourceTabs.closeAllTabs.accesskey=a
 
 # LOCALIZATION NOTE (sourceTabs.revealInTree): Editor source tab context menu item
 # for revealing source in tree.
 sourceTabs.revealInTree=Reveal in Tree
 sourceTabs.revealInTree.accesskey=r
 
 # LOCALIZATION NOTE (sourceTabs.copyLink): Editor source tab context menu item
@@ -427,16 +445,19 @@ scopes.notPaused=Not Paused
 scopes.block=Block
 
 # LOCALIZATION NOTE (sources.header): Sources left sidebar header
 sources.header=Sources
 
 # LOCALIZATION NOTE (outline.header): Outline left sidebar header
 outline.header=Outline
 
+# LOCALIZATION NOTE (outline.noFunctions): Outline text when there are no functions to display
+outline.noFunctions=No functions
+
 # LOCALIZATION NOTE (sources.search): Sources left sidebar prompt
 # e.g. Cmd+P to search. On a mac, we use the command unicode character.
 # On windows, it's ctrl.
 sources.search=%S to search
 
 # LOCALIZATION NOTE (watchExpressions.header): Watch Expressions right sidebar
 # pane header.
 watchExpressions.header=Watch Expressions
--- a/devtools/client/preferences/debugger.js
+++ b/devtools/client/preferences/debugger.js
@@ -35,8 +35,9 @@ pref("devtools.debugger.tabs", "[]");
 pref("devtools.debugger.pending-selected-location", "{}");
 pref("devtools.debugger.pending-breakpoints", "{}");
 pref("devtools.debugger.expressions", "[]");
 pref("devtools.debugger.file-search-case-sensitive", false);
 pref("devtools.debugger.file-search-whole-word", false);
 pref("devtools.debugger.file-search-regex-match", false);
 pref("devtools.debugger.features.async-stepping", true);
 pref("devtools.debugger.project-text-search-enabled", true);
+pref("devtools.debugger.features.wasm", true);
--- a/devtools/client/shared/source-map/index.js
+++ b/devtools/client/shared/source-map/index.js
@@ -67,30 +67,32 @@ return /******/ (function(modules) { // 
 
 	const { workerUtils: { WorkerDispatcher } } = __webpack_require__(6);
 
 	const dispatcher = new WorkerDispatcher();
 
 	const getOriginalURLs = dispatcher.task("getOriginalURLs");
 	const getGeneratedLocation = dispatcher.task("getGeneratedLocation");
 	const getOriginalLocation = dispatcher.task("getOriginalLocation");
+	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");
 
 	module.exports = {
 	  originalToGeneratedId,
 	  generatedToOriginalId,
 	  isGeneratedId,
 	  isOriginalId,
 	  hasMappedSource,
 	  getOriginalURLs,
 	  getGeneratedLocation,
 	  getOriginalLocation,
+	  getLocationScopes,
 	  getOriginalSourceText,
 	  applySourceMap,
 	  clearSourceMaps,
 	  startSourceMapWorker: dispatcher.start.bind(dispatcher),
 	  stopSourceMapWorker: dispatcher.stop.bind(dispatcher)
 	};
 
 /***/ },
@@ -550,16 +552,20 @@ return /******/ (function(modules) { // 
 	        const id = this.msgId++;
 	        this.worker.postMessage({ id, method, args });
 
 	        const listener = ({ data: result }) => {
 	          if (result.id !== id) {
 	            return;
 	          }
 
+	          if (!this.worker) {
+	            reject("Oops, The worker has shutdown!");
+	            return;
+	          }
 	          this.worker.removeEventListener("message", listener);
 	          if (result.error) {
 	            reject(result.error);
 	          } else {
 	            resolve(result.response);
 	          }
 	        };
 
--- a/devtools/client/shared/source-map/worker.js
+++ b/devtools/client/shared/source-map/worker.js
@@ -58,29 +58,32 @@ return /******/ (function(modules) { // 
 	 * 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 {
 	  getOriginalURLs,
 	  getGeneratedLocation,
 	  getOriginalLocation,
 	  getOriginalSourceText,
+	  getLocationScopes,
 	  hasMappedSource,
-	  applySourceMap,
-	  clearSourceMaps
+	  applySourceMap
 	} = __webpack_require__(9);
 
+	const { clearSourceMaps } = __webpack_require__(24);
+
 	const { workerUtils: { workerHandler } } = __webpack_require__(6);
 
 	// The interface is implemented in source-map to be
 	// easier to unit test.
 	self.onmessage = workerHandler({
 	  getOriginalURLs,
 	  getGeneratedLocation,
 	  getOriginalLocation,
+	  getLocationScopes,
 	  getOriginalSourceText,
 	  hasMappedSource,
 	  applySourceMap,
 	  clearSourceMaps
 	});
 
 /***/ },
 /* 1 */
@@ -539,16 +542,20 @@ return /******/ (function(modules) { // 
 	        const id = this.msgId++;
 	        this.worker.postMessage({ id, method, args });
 
 	        const listener = ({ data: result }) => {
 	          if (result.id !== id) {
 	            return;
 	          }
 
+	          if (!this.worker) {
+	            reject("Oops, The worker has shutdown!");
+	            return;
+	          }
 	          this.worker.removeEventListener("message", listener);
 	          if (result.error) {
 	            reject(result.error);
 	          } else {
 	            resolve(result.response);
 	          }
 	        };
 
@@ -636,335 +643,245 @@ return /******/ (function(modules) { // 
 	  workerHandler,
 	  streamingWorkerHandler
 	};
 
 /***/ },
 /* 9 */
 /***/ function(module, exports, __webpack_require__) {
 
-	let _resolveAndFetch = (() => {
+	let getOriginalURLs = (() => {
 	  var _ref = _asyncToGenerator(function* (generatedSource) {
-	    // Fetch the sourcemap over the network and create it.
-	    const sourceMapURL = _resolveSourceMapURL(generatedSource);
-	    const fetched = yield networkRequest(sourceMapURL, { loadFromCache: false });
-
-	    // Create the source map and fix it up.
-	    let map = new SourceMapConsumer(fetched.content);
-	    if (generatedSource.isWasm) {
-	      map = new WasmRemap(map);
-	    }
-
-	    _setSourceMapRoot(map, sourceMapURL, generatedSource);
-	    return map;
-	  });
-
-	  return function _resolveAndFetch(_x) {
-	    return _ref.apply(this, arguments);
-	  };
-	})();
-
-	let getOriginalURLs = (() => {
-	  var _ref2 = _asyncToGenerator(function* (generatedSource) {
-	    const map = yield _fetchSourceMap(generatedSource);
+	    const map = yield fetchSourceMap(generatedSource);
 	    return map && map.sources;
 	  });
 
-	  return function getOriginalURLs(_x2) {
-	    return _ref2.apply(this, arguments);
+	  return function getOriginalURLs(_x) {
+	    return _ref.apply(this, arguments);
 	  };
 	})();
 
 	let getGeneratedLocation = (() => {
-	  var _ref3 = _asyncToGenerator(function* (location, originalSource) {
+	  var _ref2 = _asyncToGenerator(function* (location, originalSource) {
 	    if (!isOriginalId(location.sourceId)) {
 	      return location;
 	    }
 
 	    const generatedSourceId = originalToGeneratedId(location.sourceId);
-	    const map = yield _getSourceMap(generatedSourceId);
+	    const map = yield getSourceMap(generatedSourceId);
 	    if (!map) {
 	      return location;
 	    }
 
 	    const { line, column } = map.generatedPositionFor({
 	      source: originalSource.url,
 	      line: location.line,
 	      column: location.column == null ? 0 : location.column,
 	      bias: SourceMapConsumer.LEAST_UPPER_BOUND
 	    });
 
 	    return {
 	      sourceId: generatedSourceId,
-	      line: line,
-	      // Treat 0 as no column so that line breakpoints work correctly.
-	      column: column === 0 ? undefined : column
+	      line,
+	      column
 	    };
 	  });
 
-	  return function getGeneratedLocation(_x3, _x4) {
-	    return _ref3.apply(this, arguments);
+	  return function getGeneratedLocation(_x2, _x3) {
+	    return _ref2.apply(this, arguments);
 	  };
 	})();
 
 	let getOriginalLocation = (() => {
-	  var _ref4 = _asyncToGenerator(function* (location) {
+	  var _ref3 = _asyncToGenerator(function* (location) {
 	    if (!isGeneratedId(location.sourceId)) {
 	      return location;
 	    }
 
-	    const map = yield _getSourceMap(location.sourceId);
+	    const map = yield getSourceMap(location.sourceId);
 	    if (!map) {
 	      return location;
 	    }
 
-	    const { source: url, line, column } = map.originalPositionFor({
+	    const { source: sourceUrl, line, column } = map.originalPositionFor({
 	      line: location.line,
-	      column: location.column == null ? Infinity : location.column
+	      column: location.column == null ? 0 : location.column
 	    });
 
-	    if (url == null) {
+	    if (sourceUrl == null) {
 	      // No url means the location didn't map.
 	      return location;
 	    }
 
 	    return {
-	      sourceId: generatedToOriginalId(location.sourceId, url),
-	      sourceUrl: url,
+	      sourceId: generatedToOriginalId(location.sourceId, sourceUrl),
+	      sourceUrl,
 	      line,
 	      column
 	    };
 	  });
 
-	  return function getOriginalLocation(_x5) {
-	    return _ref4.apply(this, arguments);
+	  return function getOriginalLocation(_x4) {
+	    return _ref3.apply(this, arguments);
 	  };
 	})();
 
 	let getOriginalSourceText = (() => {
-	  var _ref5 = _asyncToGenerator(function* (originalSource) {
+	  var _ref4 = _asyncToGenerator(function* (originalSource) {
 	    assert(isOriginalId(originalSource.id), "Source is not an original source");
 
 	    const generatedSourceId = originalToGeneratedId(originalSource.id);
-	    const map = yield _getSourceMap(generatedSourceId);
+	    const map = yield getSourceMap(generatedSourceId);
 	    if (!map) {
 	      return null;
 	    }
 
 	    let text = map.sourceContentFor(originalSource.url);
 	    if (!text) {
 	      text = (yield networkRequest(originalSource.url, { loadFromCache: false })).content;
 	    }
 
 	    return {
 	      text,
 	      contentType: getContentType(originalSource.url || "")
 	    };
 	  });
 
-	  return function getOriginalSourceText(_x6) {
+	  return function getOriginalSourceText(_x5) {
+	    return _ref4.apply(this, arguments);
+	  };
+	})();
+
+	/**
+	 * Finds the scope binding information at the source map based on locations and
+	 * generated source scopes. The generated source scopes contain variables names
+	 * and all their references in the generated source. This information is merged
+	 * with the source map original names information and returned as result.
+	 * @memberof utils/source-map-worker
+	 * @static
+	 */
+
+
+	let getLocationScopes = (() => {
+	  var _ref5 = _asyncToGenerator(function* (location, generatedSourceScopes) {
+	    if (!isGeneratedId(location.sourceId)) {
+	      return null;
+	    }
+
+	    const map = yield getSourceMap(location.sourceId);
+	    if (!map) {
+	      return null;
+	    }
+
+	    return getLocationScopesFromMap(map, generatedSourceScopes, location);
+	  });
+
+	  return function getLocationScopes(_x6, _x7) {
 	    return _ref5.apply(this, arguments);
 	  };
 	})();
 
 	let hasMappedSource = (() => {
 	  var _ref6 = _asyncToGenerator(function* (location) {
 	    if (isOriginalId(location.sourceId)) {
 	      return true;
 	    }
 
 	    const loc = yield getOriginalLocation(location);
 	    return loc.sourceId !== location.sourceId;
 	  });
 
-	  return function hasMappedSource(_x7) {
+	  return function hasMappedSource(_x8) {
 	    return _ref6.apply(this, arguments);
 	  };
 	})();
 
 	function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
 
 	/* 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 Map Worker
 	 * @module utils/source-map-worker
 	 */
 
 	const { networkRequest } = __webpack_require__(6);
-
-	const path = __webpack_require__(10);
-	const { SourceMapConsumer, SourceMapGenerator } = __webpack_require__(11);
+	const { SourceMapConsumer, SourceMapGenerator } = __webpack_require__(10);
+	const path = __webpack_require__(21);
+
 	const assert = __webpack_require__(22);
+	const { fetchSourceMap } = __webpack_require__(23);
+	const {
+	  getSourceMap,
+	  setSourceMap,
+	  clearSourceMaps
+	} = __webpack_require__(24);
 	const {
 	  originalToGeneratedId,
 	  generatedToOriginalId,
 	  isGeneratedId,
 	  isOriginalId,
 	  getContentType
 	} = __webpack_require__(1);
-	const { WasmRemap } = __webpack_require__(23);
-
-	let sourceMapRequests = new Map();
-
-	function clearSourceMaps() {
-	  sourceMapRequests.clear();
-	}
-
-	function _resolveSourceMapURL(source) {
-	  const { url = "", sourceMapURL = "" } = source;
-	  if (path.isURL(sourceMapURL) || url == "") {
-	    // If it's already a full URL or the source doesn't have a URL,
-	    // don't resolve anything.
-	    return sourceMapURL;
-	  } else if (path.isAbsolute(sourceMapURL)) {
-	    // If it's an absolute path, it should be resolved relative to the
-	    // host of the source.
-	    const { protocol = "", host = "" } = new URL(url);
-	    return `${protocol}//${host}${sourceMapURL}`;
-	  }
-	  // Otherwise, it's a relative path and should be resolved relative
-	  // to the source.
-	  return `${path.dirname(url)}/${sourceMapURL}`;
-	}
-
-	/**
-	 * Sets the source map's sourceRoot to be relative to the source map url.
-	 * @memberof utils/source-map-worker
-	 * @static
-	 */
-	function _setSourceMapRoot(sourceMap, absSourceMapURL, source) {
-	  // No need to do this fiddling if we won't be fetching any sources over the
-	  // wire.
-	  if (sourceMap.hasContentsOfAllSources()) {
-	    return;
-	  }
-
-	  // If it's already a URL, just leave it alone.
-	  if (!path.isURL(sourceMap.sourceRoot)) {
-	    // In the odd case where the sourceMap is a data: URL and it does
-	    // not contain the full sources, fall back to using the source's
-	    // URL, if possible.
-	    let parsedSourceMapURL = new URL(absSourceMapURL);
-	    if (parsedSourceMapURL.protocol === "data:" && source.url) {
-	      parsedSourceMapURL = new URL(source.url);
-	    }
-
-	    parsedSourceMapURL.pathname = path.dirname(parsedSourceMapURL.pathname);
-	    sourceMap.sourceRoot = new URL(sourceMap.sourceRoot || "", parsedSourceMapURL).toString();
-	  }
-	  return sourceMap.sourceRoot;
-	}
-
-	function _getSourceMap(generatedSourceId) {
-	  return sourceMapRequests.get(generatedSourceId);
-	}
-
-	function _fetchSourceMap(generatedSource) {
-	  const existingRequest = sourceMapRequests.get(generatedSource.id);
-	  if (existingRequest) {
-	    // If it has already been requested, return the request. Make sure
-	    // to do this even if sourcemapping is turned off, because
-	    // pretty-printing uses sourcemaps.
-	    //
-	    // An important behavior here is that if it's in the middle of
-	    // requesting it, all subsequent calls will block on the initial
-	    // request.
-	    return existingRequest;
-	  } else if (!generatedSource.sourceMapURL) {
-	    return Promise.resolve(null);
-	  }
-
-	  // Fire off the request, set it in the cache, and return it.
-	  const req = _resolveAndFetch(generatedSource);
-	  // Make sure the cached promise does not reject, because we only
-	  // want to report the error once.
-	  sourceMapRequests.set(generatedSource.id, req.catch(() => null));
-	  return req;
-	}
+	const {
+	  getLocationScopes: getLocationScopesFromMap
+	} = __webpack_require__(26);
+
+	const { WasmRemap } = __webpack_require__(25);
 
 	function applySourceMap(generatedId, url, code, mappings) {
 	  const generator = new SourceMapGenerator({ file: url });
 	  mappings.forEach(mapping => generator.addMapping(mapping));
 	  generator.setSourceContent(url, code);
 
 	  const map = SourceMapConsumer(generator.toJSON());
-	  sourceMapRequests.set(generatedId, Promise.resolve(map));
+	  setSourceMap(generatedId, Promise.resolve(map));
 	}
 
 	module.exports = {
 	  getOriginalURLs,
 	  getGeneratedLocation,
 	  getOriginalLocation,
 	  getOriginalSourceText,
+	  getLocationScopes,
 	  applySourceMap,
 	  clearSourceMaps,
 	  hasMappedSource
 	};
 
 /***/ },
 /* 10 */
-/***/ function(module, exports) {
-
-	/* This Source Code Form is subject to the terms of the Mozilla Public
-	 * License, v. 2.0. If a copy of the MPL was not distributed with this
-	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-	function dirname(path) {
-	  const idx = path.lastIndexOf("/");
-	  return path.slice(0, idx);
-	}
-
-	function isURL(str) {
-	  try {
-	    new URL(str);
-	    return true;
-	  } catch (e) {
-	    return false;
-	  }
-	}
-
-	function isAbsolute(str) {
-	  return str[0] === "/";
-	}
-
-	module.exports = {
-	  dirname, isURL, isAbsolute
-	};
-
-/***/ },
-/* 11 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/*
 	 * Copyright 2009-2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE.txt or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
-	exports.SourceMapGenerator = __webpack_require__(12).SourceMapGenerator;
-	exports.SourceMapConsumer = __webpack_require__(18).SourceMapConsumer;
-	exports.SourceNode = __webpack_require__(21).SourceNode;
+	exports.SourceMapGenerator = __webpack_require__(11).SourceMapGenerator;
+	exports.SourceMapConsumer = __webpack_require__(17).SourceMapConsumer;
+	exports.SourceNode = __webpack_require__(20).SourceNode;
 
 /***/ },
-/* 12 */
+/* 11 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
 
-	var base64VLQ = __webpack_require__(13);
-	var util = __webpack_require__(15);
-	var ArraySet = __webpack_require__(16).ArraySet;
-	var MappingList = __webpack_require__(17).MappingList;
+	var base64VLQ = __webpack_require__(12);
+	var util = __webpack_require__(14);
+	var ArraySet = __webpack_require__(15).ArraySet;
+	var MappingList = __webpack_require__(16).MappingList;
 
 	/**
 	 * An instance of the SourceMapGenerator represents a source map which is
 	 * being built incrementally. You may pass an object with the following
 	 * properties:
 	 *
 	 *   - file: The filename of the generated source.
 	 *   - sourceRoot: A root for all relative URLs in this source map.
@@ -1322,17 +1239,17 @@ return /******/ (function(modules) { // 
 	 */
 	SourceMapGenerator.prototype.toString = function SourceMapGenerator_toString() {
 	  return JSON.stringify(this.toJSON());
 	};
 
 	exports.SourceMapGenerator = SourceMapGenerator;
 
 /***/ },
-/* 13 */
+/* 12 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 *
@@ -1362,17 +1279,17 @@ return /******/ (function(modules) { // 
 	 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 	 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 	 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 	 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 	 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 	 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 	 */
 
-	var base64 = __webpack_require__(14);
+	var base64 = __webpack_require__(13);
 
 	// A single base 64 digit can contain 6 bits of data. For the base 64 variable
 	// length quantities we use in the source map spec, the first bit is the sign,
 	// the next four bits are the actual value, and the 6th bit is the
 	// continuation bit. The continuation bit tells us whether there are more
 	// digits in this value following this digit.
 	//
 	//   Continuation
@@ -1463,17 +1380,17 @@ return /******/ (function(modules) { // 
 	    shift += VLQ_BASE_SHIFT;
 	  } while (continuation);
 
 	  aOutParam.value = fromVLQSigned(result);
 	  aOutParam.rest = aIndex;
 	};
 
 /***/ },
-/* 14 */
+/* 13 */
 /***/ function(module, exports) {
 
 	/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
@@ -1535,17 +1452,17 @@ return /******/ (function(modules) { // 
 	    return 63;
 	  }
 
 	  // Invalid base64 digit.
 	  return -1;
 	};
 
 /***/ },
-/* 15 */
+/* 14 */
 /***/ function(module, exports) {
 
 	/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
@@ -1947,27 +1864,27 @@ return /******/ (function(modules) { // 
 	    return cmp;
 	  }
 
 	  return strcmp(mappingA.name, mappingB.name);
 	}
 	exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated;
 
 /***/ },
-/* 16 */
+/* 15 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
 
-	var util = __webpack_require__(15);
+	var util = __webpack_require__(14);
 	var has = Object.prototype.hasOwnProperty;
 
 	/**
 	 * A data structure which is a combination of an array and a set. Adding a new
 	 * member is O(1), testing for membership is O(1), and finding the index of an
 	 * element is O(1). Removing elements from the set is not supported. Only
 	 * strings are supported for membership.
 	 */
@@ -2056,27 +1973,27 @@ return /******/ (function(modules) { // 
 	 */
 	ArraySet.prototype.toArray = function ArraySet_toArray() {
 	  return this._array.slice();
 	};
 
 	exports.ArraySet = ArraySet;
 
 /***/ },
-/* 17 */
+/* 16 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2014 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
 
-	var util = __webpack_require__(15);
+	var util = __webpack_require__(14);
 
 	/**
 	 * Determine whether mappingB is after mappingA with respect to generated
 	 * position.
 	 */
 	function generatedPositionAfter(mappingA, mappingB) {
 	  // Optimized for most common case
 	  var lineA = mappingA.generatedLine;
@@ -2138,31 +2055,31 @@ return /******/ (function(modules) { // 
 	    this._sorted = true;
 	  }
 	  return this._array;
 	};
 
 	exports.MappingList = MappingList;
 
 /***/ },
-/* 18 */
+/* 17 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
 
-	var util = __webpack_require__(15);
-	var binarySearch = __webpack_require__(19);
-	var ArraySet = __webpack_require__(16).ArraySet;
-	var base64VLQ = __webpack_require__(13);
-	var quickSort = __webpack_require__(20).quickSort;
+	var util = __webpack_require__(14);
+	var binarySearch = __webpack_require__(18);
+	var ArraySet = __webpack_require__(15).ArraySet;
+	var base64VLQ = __webpack_require__(12);
+	var quickSort = __webpack_require__(19).quickSort;
 
 	function SourceMapConsumer(aSourceMap) {
 	  var sourceMap = aSourceMap;
 	  if (typeof aSourceMap === 'string') {
 	    sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, ''));
 	  }
 
 	  return sourceMap.sections != null ? new IndexedSourceMapConsumer(sourceMap) : new BasicSourceMapConsumer(sourceMap);
@@ -3157,17 +3074,17 @@ return /******/ (function(modules) { // 
 
 	  quickSort(this.__generatedMappings, util.compareByGeneratedPositionsDeflated);
 	  quickSort(this.__originalMappings, util.compareByOriginalPositions);
 	};
 
 	exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer;
 
 /***/ },
-/* 19 */
+/* 18 */
 /***/ function(module, exports) {
 
 	/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
@@ -3270,17 +3187,17 @@ return /******/ (function(modules) { // 
 	    }
 	    --index;
 	  }
 
 	  return index;
 	};
 
 /***/ },
-/* 20 */
+/* 19 */
 /***/ function(module, exports) {
 
 	/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
@@ -3389,28 +3306,28 @@ return /******/ (function(modules) { // 
 	 * @param {function} comparator
 	 *        Function to use to compare two items.
 	 */
 	exports.quickSort = function (ary, comparator) {
 	  doQuickSort(ary, comparator, 0, ary.length - 1);
 	};
 
 /***/ },
-/* 21 */
+/* 20 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* -*- Mode: js; js-indent-level: 2; -*- */
 	/*
 	 * Copyright 2011 Mozilla Foundation and contributors
 	 * Licensed under the New BSD license. See LICENSE or:
 	 * http://opensource.org/licenses/BSD-3-Clause
 	 */
 
-	var SourceMapGenerator = __webpack_require__(12).SourceMapGenerator;
-	var util = __webpack_require__(15);
+	var SourceMapGenerator = __webpack_require__(11).SourceMapGenerator;
+	var util = __webpack_require__(14);
 
 	// Matches a Windows-style `\r\n` newline or a `\n` newline used by all other
 	// operating systems these days (capturing the result).
 	var REGEX_NEWLINE = /(\r?\n)/;
 
 	// Newline character code for charCodeAt() comparisons
 	var NEWLINE_CODE = 10;
 
@@ -3775,16 +3692,46 @@ return /******/ (function(modules) { // 
 	  });
 
 	  return { code: generated.code, map: map };
 	};
 
 	exports.SourceNode = SourceNode;
 
 /***/ },
+/* 21 */
+/***/ function(module, exports) {
+
+	/* This Source Code Form is subject to the terms of the Mozilla Public
+	 * License, v. 2.0. If a copy of the MPL was not distributed with this
+	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+	function dirname(path) {
+	  const idx = path.lastIndexOf("/");
+	  return path.slice(0, idx);
+	}
+
+	function isURL(str) {
+	  try {
+	    new URL(str);
+	    return true;
+	  } catch (e) {
+	    return false;
+	  }
+	}
+
+	function isAbsolute(str) {
+	  return str[0] === "/";
+	}
+
+	module.exports = {
+	  dirname, isURL, isAbsolute
+	};
+
+/***/ },
 /* 22 */
 /***/ function(module, exports) {
 
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 	function assert(condition, message) {
@@ -3792,16 +3739,157 @@ return /******/ (function(modules) { // 
 	    throw new Error(`Assertion failure: ${message}`);
 	  }
 	}
 
 	module.exports = assert;
 
 /***/ },
 /* 23 */
+/***/ function(module, exports, __webpack_require__) {
+
+	let _resolveAndFetch = (() => {
+	  var _ref = _asyncToGenerator(function* (generatedSource) {
+	    // Fetch the sourcemap over the network and create it.
+	    const sourceMapURL = _resolveSourceMapURL(generatedSource);
+
+	    const fetched = yield networkRequest(sourceMapURL, { loadFromCache: false });
+
+	    // Create the source map and fix it up.
+	    let map = new SourceMapConsumer(fetched.content);
+	    if (generatedSource.isWasm) {
+	      map = new WasmRemap(map);
+	    }
+
+	    _setSourceMapRoot(map, sourceMapURL, generatedSource);
+	    return map;
+	  });
+
+	  return function _resolveAndFetch(_x) {
+	    return _ref.apply(this, arguments);
+	  };
+	})();
+
+	function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
+
+	/* 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__(6);
+	const { getSourceMap, setSourceMap } = __webpack_require__(24);
+	const { WasmRemap } = __webpack_require__(25);
+	const { SourceMapConsumer } = __webpack_require__(10);
+
+	const path = __webpack_require__(21);
+
+	/**
+	 * Sets the source map's sourceRoot to be relative to the source map url.
+	 * @memberof utils/source-map-worker
+	 * @static
+	 */
+	function _setSourceMapRoot(sourceMap, absSourceMapURL, source) {
+	  // No need to do this fiddling if we won't be fetching any sources over the
+	  // wire.
+	  if (sourceMap.hasContentsOfAllSources()) {
+	    return;
+	  }
+
+	  // If it's already a URL, just leave it alone.
+	  if (!path.isURL(sourceMap.sourceRoot)) {
+	    // In the odd case where the sourceMap is a data: URL and it does
+	    // not contain the full sources, fall back to using the source's
+	    // URL, if possible.
+	    let parsedSourceMapURL = new URL(absSourceMapURL);
+
+	    if (parsedSourceMapURL.protocol === "data:" && source.url) {
+	      parsedSourceMapURL = new URL(source.url);
+	    }
+
+	    parsedSourceMapURL.pathname = path.dirname(parsedSourceMapURL.pathname);
+	    sourceMap.sourceRoot = new URL(sourceMap.sourceRoot || "", parsedSourceMapURL).toString();
+	  }
+	  return sourceMap.sourceRoot;
+	}
+
+	function _resolveSourceMapURL(source) {
+	  const { url = "", sourceMapURL = "" } = source;
+	  if (path.isURL(sourceMapURL) || url == "") {
+	    // If it's already a full URL or the source doesn't have a URL,
+	    // don't resolve anything.
+	    return sourceMapURL;
+	  }
+
+	  if (path.isAbsolute(sourceMapURL)) {
+	    // If it's an absolute path, it should be resolved relative to the
+	    // host of the source.
+	    const { protocol = "", host = "" } = new URL(url);
+	    return `${protocol}//${host}${sourceMapURL}`;
+	  }
+
+	  // Otherwise, it's a relative path and should be resolved relative
+	  // to the source.
+	  return `${path.dirname(url)}/${sourceMapURL}`;
+	}
+
+	function fetchSourceMap(generatedSource) {
+	  const existingRequest = getSourceMap(generatedSource.id);
+
+	  // If it has already been requested, return the request. Make sure
+	  // to do this even if sourcemapping is turned off, because
+	  // pretty-printing uses sourcemaps.
+	  //
+	  // An important behavior here is that if it's in the middle of
+	  // requesting it, all subsequent calls will block on the initial
+	  // request.
+	  if (existingRequest) {
+	    return existingRequest;
+	  }
+
+	  if (!generatedSource.sourceMapURL) {
+	    return Promise.resolve(null);
+	  }
+
+	  // Fire off the request, set it in the cache, and return it.
+	  const req = _resolveAndFetch(generatedSource);
+	  // Make sure the cached promise does not reject, because we only
+	  // want to report the error once.
+	  setSourceMap(generatedSource.id, req.catch(() => null));
+	  return req;
+	}
+
+	module.exports = { fetchSourceMap };
+
+/***/ },
+/* 24 */
+/***/ function(module, exports) {
+
+	
+	let sourceMapRequests = new Map();
+
+	function clearSourceMaps() {
+	  sourceMapRequests.clear();
+	}
+
+	function getSourceMap(generatedSourceId) {
+	  return sourceMapRequests.get(generatedSourceId);
+	}
+
+	function setSourceMap(generatedId, request) {
+	  sourceMapRequests.set(generatedId, request);
+	}
+
+	module.exports = {
+	  clearSourceMaps,
+	  getSourceMap,
+	  setSourceMap
+	};
+
+/***/ },
+/* 25 */
 /***/ function(module, exports) {
 
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 	"use strict";
 
@@ -3911,12 +3999,3014 @@ return /******/ (function(modules) { // 
 	        name
 	      });
 	    }, context, order);
 	  }
 	}
 
 	exports.WasmRemap = WasmRemap;
 
+/***/ },
+/* 26 */
+/***/ 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 { SourceMapConsumer } = __webpack_require__(27);
+
+	function comparePositions(a, b) {
+	  if (a.line === b.line) {
+	    return a.column - b.column;
+	  } else {
+	    return a.line - b.line;
+	  }
+	}
+
+	function getOriginalPositionName(map, generatedPosition) {
+	  const originalPosition = map.originalPositionFor(generatedPosition);
+	  if (!originalPosition || !originalPosition.name) {
+	    return null;
+	  }
+	  // Verify if it's the exact position.
+	  const originalPositionTest = map.originalPositionFor({
+	    line: generatedPosition.line,
+	    column: generatedPosition.column,
+	    bias: SourceMapConsumer.LEAST_UPPER_BOUND
+	  });
+	  if (!originalPositionTest || originalPositionTest.column !== originalPosition.column || originalPositionTest.line !== originalPosition.line) {
+	    return null;
+	  }
+	  return originalPosition.name;
+	}
+
+	// The `scope` has bindings that contains positions/references to the
+	// generated names (these may has different original name). Going over all
+	// these names and positions, to check what original name is listed there.
+	// To make things more interesting the same generated name can potentially
+	// be used for different original names, so building trackedBindings for all
+	// names and positions.
+	// Example of MappedScopeBindings:
+	// ```
+	// { type: 'block',
+	//   bindings: {
+	//     'current': 't',
+	//     'start': 't',
+	//     'end': 'e'
+	//   } }
+	// ```
+
+	function applyBestNamePosition(trackedBindings, generatedName, nameLocation, map, currentPosition) {
+	  const namePosition = {
+	    line: nameLocation.line,
+	    column: nameLocation.column || 0
+	  };
+	  const originalName = getOriginalPositionName(map, namePosition);
+	  if (!originalName) {
+	    return trackedBindings;
+	  }
+
+	  let trackedBinding = trackedBindings[originalName];
+	  if (!trackedBinding) {
+	    // No best position was found for original name yet -- using first
+	    // found position.
+	    trackedBindings[originalName] = {
+	      generatedName,
+	      bestPosition: namePosition
+	    };
+	  } else if (comparePositions(namePosition, currentPosition) <= 0) {
+	    // The position is before location, the more recient will have needed
+	    // name assignment, also discard all positions past currentPosition.
+	    if (comparePositions(trackedBinding.bestPosition, namePosition) < 0 || comparePositions(trackedBinding.bestPosition, currentPosition) > 0) {
+	      trackedBinding.generatedName = generatedName;
+	      trackedBinding.bestPosition = namePosition;
+	    }
+	  } else {
+	    // The position is past location, need to select more recient after
+	    // specified location, but only if "before" bestPosition is not found.
+	    if (comparePositions(trackedBinding.bestPosition, namePosition) > 0 && comparePositions(trackedBinding.bestPosition, currentPosition) < 0) {
+	      trackedBinding.generatedName = generatedName;
+	      trackedBinding.bestPosition = namePosition;
+	    }
+	  }
+	  return trackedBindings;
+	}
+
+	function applyTrackedBindings(trackedBindings, generatedName, locations, map, currentPosition) {
+	  return locations.reduce((trackedBindings, nameLocation) => applyBestNamePosition(trackedBindings, generatedName, nameLocation, map, currentPosition), trackedBindings);
+	}
+
+	/**
+	 * Finds the scope binding information at the source map based on locations and
+	 * generated source scopes. The generated source scopes contain variables names
+	 * and all their references in the generated source. This information is merged
+	 * with the source map original names information and returned as result.
+	 */
+	function getLocationScopes(map, generatedSourceScopes, location) {
+	  const currentPosition = {
+	    line: location.line,
+	    column: location.column || 0
+	  };
+
+	  return generatedSourceScopes.map(scope => {
+	    const trackedBindings = Object.keys(scope.bindings).reduce((trackedBindings, generatedName) => applyTrackedBindings(trackedBindings, generatedName, scope.bindings[generatedName], map, currentPosition), Object.create(null));
+
+	    const bindings = Object.keys(trackedBindings).reduce((bindings, name) => {
+	      const { generatedName } = trackedBindings[name];
+	      // No need to record the binding if generated name matches original one.
+	      if (name !== generatedName) {
+	        bindings[name] = generatedName;
+	      }
+	      return bindings;
+	    }, Object.create(null));
+	    return {
+	      type: scope.type,
+	      bindings
+	    };
+	  });
+	}
+
+	module.exports = {
+	  getLocationScopes
+	};
+
+/***/ },
+/* 27 */
+/***/ function(module, exports, __webpack_require__) {
+
+	/*
+	 * Copyright 2009-2011 Mozilla Foundation and contributors
+	 * Licensed under the New BSD license. See LICENSE.txt or:
+	 * http://opensource.org/licenses/BSD-3-Clause
+	 */
+	exports.SourceMapGenerator = __webpack_require__(28).SourceMapGenerator;
+	exports.SourceMapConsumer = __webpack_require__(34).SourceMapConsumer;
+	exports.SourceNode = __webpack_require__(37).SourceNode;
+
+/***/ },
+/* 28 */
+/***/ function(module, exports, __webpack_require__) {
+
+	/* -*- Mode: js; js-indent-level: 2; -*- */
+	/*
+	 * Copyright 2011 Mozilla Foundation and contributors
+	 * Licensed under the New BSD license. See LICENSE or:
+	 * http://opensource.org/licenses/BSD-3-Clause
+	 */
+
+	var base64VLQ = __webpack_require__(29);
+	var util = __webpack_require__(31);
+	var ArraySet = __webpack_require__(32).ArraySet;
+	var MappingList = __webpack_require__(33).MappingList;
+
+	/**
+	 * An instance of the SourceMapGenerator represents a source map which is
+	 * being built incrementally. You may pass an object with the following
+	 * properties:
+	 *
+	 *   - file: The filename of the generated source.
+	 *   - sourceRoot: A root for all relative URLs in this source map.
+	 */
+	function SourceMapGenerator(aArgs) {
+	  if (!aArgs) {
+	    aArgs = {};
+	  }
+	  this._file = util.getArg(aArgs, 'file', null);
+	  this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null);
+	  this._skipValidation = util.getArg(aArgs, 'skipValidation', false);
+	  this._sources = new ArraySet();
+	  this._names = new ArraySet();
+	  this._mappings = new MappingList();
+	  this._sourcesContents = null;
+	}
+
+	SourceMapGenerator.prototype._version = 3;
+
+	/**
+	 * Creates a new SourceMapGenerator based on a SourceMapConsumer
+	 *
+	 * @param aSourceMapConsumer The SourceMap.
+	 */
+	SourceMapGenerator.fromSourceMap = function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) {
+	  var sourceRoot = aSourceMapConsumer.sourceRoot;
+	  var generator = new SourceMapGenerator({
+	    file: aSourceMapConsumer.file,
+	    sourceRoot: sourceRoot
+	  });
+	  aSourceMapConsumer.eachMapping(function (mapping) {
+	    var newMapping = {
+	      generated: {
+	        line: mapping.generatedLine,
+	        column: mapping.generatedColumn
+	      }
+	    };
+
+	    if (mapping.source != null) {
+	      newMapping.source = mapping.source;
+	      if (sourceRoot != null) {
+	        newMapping.source = util.relative(sourceRoot, newMapping.source);
+	      }
+
+	      newMapping.original = {
+	        line: mapping.originalLine,
+	        column: mapping.originalColumn
+	      };
+
+	      if (mapping.name != null) {
+	        newMapping.name = mapping.name;
+	      }
+	    }
+
+	    generator.addMapping(newMapping);
+	  });
+	  aSourceMapConsumer.sources.forEach(function (sourceFile) {
+	    var content = aSourceMapConsumer.sourceContentFor(sourceFile);
+	    if (content != null) {
+	      generator.setSourceContent(sourceFile, content);
+	    }
+	  });
+	  return generator;
+	};
+
+	/**
+	 * Add a single mapping from original source line and column to the generated
+	 * source's line and column for this source map being created. The mapping
+	 * object should have the following properties:
+	 *
+	 *   - generated: An object with the generated line and column positions.
+	 *   - original: An object with the original line and column positions.
+	 *   - source: The original source file (relative to the sourceRoot).
+	 *   - name: An optional original token name for this mapping.
+	 */
+	SourceMapGenerator.prototype.addMapping = function SourceMapGenerator_addMapping(aArgs) {
+	  var generated = util.getArg(aArgs, 'generated');
+	  var original = util.getArg(aArgs, 'original', null);
+	  var source = util.getArg(aArgs, 'source', null);
+	  var name = util.getArg(aArgs, 'name', null);
+
+	  if (!this._skipValidation) {
+	    this._validateMapping(generated, original, source, name);
+	  }
+
+	  if (source != null) {
+	    source = String(source);
+	    if (!this._sources.has(source)) {
+	      this._sources.add(source);
+	    }
+	  }
+
+	  if (name != null) {
+	    name = String(name);
+	    if (!this._names.has(name)) {
+	      this._names.add(name);
+	    }
+	  }
+
+	  this._mappings.add({
+	    generatedLine: generated.line,
+	    generatedColumn: generated.column,
+	    originalLine: original != null && original.line,
+	    originalColumn: original != null && original.column,
+	    source: source,
+	    name: name
+	  });
+	};
+
+	/**
+	 * Set the source content for a source file.
+	 */
+	SourceMapGenerator.prototype.setSourceContent = function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) {
+	  var source = aSourceFile;
+	  if (this._sourceRoot != null) {
+	    source = util.relative(this._sourceRoot, source);
+	  }
+
+	  if (aSourceContent != null) {
+	    // Add the source content to the _sourcesContents map.
+	    // Create a new _sourcesContents map if the property is null.
+	    if (!this._sourcesContents) {
+	      this._sourcesContents = Object.create(null);
+	    }
+	    this._sourcesContents[util.toSetString(source)] = aSourceContent;
+	  } else if (this._sourcesContents) {
+	    // Remove the source file from the _sourcesContents map.
+	    // If the _sourcesContents map is empty, set the property to null.
+	    delete this._sourcesContents[util.toSetString(source)];
+	    if (Object.keys(this._sourcesContents).length === 0) {
+	      this._sourcesContents = null;
+	    }
+	  }
+	};
+
+	/**
+	 * Applies the mappings of a sub-source-map for a specific source file to the
+	 * source map being generated. Each mapping to the supplied source file is
+	 * rewritten using the supplied source map. Note: The resolution for the
+	 * resulting mappings is the minimium of this map and the supplied map.
+	 *
+	 * @param aSourceMapConsumer The source map to be applied.
+	 * @param aSourceFile Optional. The filename of the source file.
+	 *        If omitted, SourceMapConsumer's file property will be used.
+	 * @param aSourceMapPath Optional. The dirname of the path to the source map
+	 *        to be applied. If relative, it is relative to the SourceMapConsumer.
+	 *        This parameter is needed when the two source maps aren't in the same
+	 *        directory, and the source map to be applied contains relative source
+	 *        paths. If so, those relative source paths need to be rewritten
+	 *        relative to the SourceMapGenerator.
+	 */
+	SourceMapGenerator.prototype.applySourceMap = function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) {
+	  var sourceFile = aSourceFile;
+	  // If aSourceFile is omitted, we will use the file property of the SourceMap
+	  if (aSourceFile == null) {
+	    if (aSourceMapConsumer.file == null) {
+	      throw new Error('SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' + 'or the source map\'s "file" property. Both were omitted.');
+	    }
+	    sourceFile = aSourceMapConsumer.file;
+	  }
+	  var sourceRoot = this._sourceRoot;
+	  // Make "sourceFile" relative if an absolute Url is passed.
+	  if (sourceRoot != null) {
+	    sourceFile = util.relative(sourceRoot, sourceFile);
+	  }
+	  // Applying the SourceMap can add and remove items from the sources and
+	  // the names array.
+	  var newSources = new ArraySet();
+	  var newNames = new ArraySet();
+
+	  // Find mappings for the "sourceFile"
+	  this._mappings.unsortedForEach(function (mapping) {
+	    if (mapping.source === sourceFile && mapping.originalLine != null) {
+	      // Check if it can be mapped by the source map, then update the mapping.
+	      var original = aSourceMapConsumer.originalPositionFor({
+	        line: mapping.originalLine,
+	        column: mapping.originalColumn
+	      });
+	      if (original.source != null) {
+	        // Copy mapping
+	        mapping.source = original.source;
+	        if (aSourceMapPath != null) {
+	          mapping.source = util.join(aSourceMapPath, mapping.source);
+	        }
+	        if (sourceRoot != null) {
+	          mapping.source = util.relative(sourceRoot, mapping.source);
+	        }
+	        mapping.originalLine = original.line;
+	        mapping.originalColumn = original.column;
+	        if (original.name != null) {
+	          mapping.name = original.name;
+	        }
+	      }
+	    }
+
+	    var source = mapping.source;
+	    if (source != null && !newSources.has(source)) {
+	      newSources.add(source);
+	    }
+
+	    var name = mapping.name;
+	    if (name != null && !newNames.has(name)) {
+	      newNames.add(name);
+	    }
+	  }, this);
+	  this._sources = newSources;
+	  this._names = newNames;
+
+	  // Copy sourcesContents of applied map.
+	  aSourceMapConsumer.sources.forEach(function (sourceFile) {
+	    var content = aSourceMapConsumer.sourceContentFor(sourceFile);
+	    if (content != null) {
+	      if (aSourceMapPath != null) {
+	        sourceFile = util.join(aSourceMapPath, sourceFile);
+	      }
+	      if (sourceRoot != null) {
+	        sourceFile = util.relative(sourceRoot, sourceFile);
+	      }
+	      this.setSourceContent(sourceFile, content);
+	    }
+	  }, this);
+	};
+
+	/**
+	 * A mapping can have one of the three levels of data:
+	 *
+	 *   1. Just the generated position.
+	 *   2. The Generated position, original position, and original source.
+	 *   3. Generated and original position, original source, as well as a name
+	 *      token.
+	 *
+	 * To maintain consistency, we validate that any new mapping being added falls
+	 * in to one of these categories.
+	 */
+	SourceMapGenerator.prototype._validateMapping = function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, aName) {
+	  // When aOriginal is truthy but has empty values for .line and .column,
+	  // it is most likely a programmer error. In this case we throw a very
+	  // specific error message to try to guide them the right way.
+	  // For example: https://github.com/Polymer/polymer-bundler/pull/519
+	  if (aOriginal && typeof aOriginal.line !== 'number' && typeof aOriginal.column !== 'number') {
+	    throw new Error('original.line and original.column are not numbers -- you probably meant to omit ' + 'the original mapping entirely and only map the generated position. If so, pass ' + 'null for the original mapping instead of an object with empty or null values.');
+	  }
+
+	  if (aGenerated && 'line' in aGenerated && 'column' in aGenerated && aGenerated.line > 0 && aGenerated.column >= 0 && !aOriginal && !aSource && !aName) {
+	    // Case 1.
+	    return;
+	  } else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated && aOriginal && 'line' in aOriginal && 'column' in aOriginal && aGenerated.line > 0 && aGenerated.column >= 0 && aOriginal.line > 0 && aOriginal.column >= 0 && aSource) {
+	    // Cases 2 and 3.
+	    return;
+	  } else {
+	    throw new Error('Invalid mapping: ' + JSON.stringify({
+	      generated: aGenerated,
+	      source: aSource,
+	      original: aOriginal,
+	      name: aName
+	    }));
+	  }
+	};
+
+	/**
+	 * Serialize the accumulated mappings in to the stream of base 64 VLQs
+	 * specified by the source map format.
+	 */
+	SourceMapGenerator.prototype._serializeMappings = function SourceMapGenerator_serializeMappings() {
+	  var previousGeneratedColumn = 0;
+	  var previousGeneratedLine = 1;
+	  var previousOriginalColumn = 0;
+	  var previousOriginalLine = 0;
+	  var previousName = 0;
+	  var previousSource = 0;
+	  var result = '';
+	  var next;
+	  var mapping;
+	  var nameIdx;
+	  var sourceIdx;
+
+	  var mappings = this._mappings.toArray();
+	  for (var i = 0, len = mappings.length; i < len; i++) {
+	    mapping = mappings[i];
+	    next = '';
+
+	    if (mapping.generatedLine !== previousGeneratedLine) {
+	      previousGeneratedColumn = 0;
+	      while (mapping.generatedLine !== previousGeneratedLine) {
+	        next += ';';
+	        previousGeneratedLine++;
+	      }
+	    } else {
+	      if (i > 0) {
+	        if (!util.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) {
+	          continue;
+	        }
+	        next += ',';
+	      }
+	    }
+
+	    next += base64VLQ.encode(mapping.generatedColumn - previousGeneratedColumn);
+	    previousGeneratedColumn = mapping.generatedColumn;
+
+	    if (mapping.source != null) {
+	      sourceIdx = this._sources.indexOf(mapping.source);
+	      next += base64VLQ.encode(sourceIdx - previousSource);
+	      previousSource = sourceIdx;
+
+	      // lines are stored 0-based in SourceMap spec version 3
+	      next += base64VLQ.encode(mapping.originalLine - 1 - previousOriginalLine);
+	      previousOriginalLine = mapping.originalLine - 1;
+
+	      next += base64VLQ.encode(mapping.originalColumn - previousOriginalColumn);
+	      previousOriginalColumn = mapping.originalColumn;
+
+	      if (mapping.name != null) {
+	        nameIdx = this._names.indexOf(mapping.name);
+	        next += base64VLQ.encode(nameIdx - previousName);
+	        previousName = nameIdx;
+	      }
+	    }
+
+	    result += next;
+	  }
+
+	  return result;
+	};
+
+	SourceMapGenerator.prototype._generateSourcesContent = function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) {
+	  return aSources.map(function (source) {
+	    if (!this._sourcesContents) {
+	      return null;
+	    }
+	    if (aSourceRoot != null) {
+	      source = util.relative(aSourceRoot, source);
+	    }
+	    var key = util.toSetString(source);
+	    return Object.prototype.hasOwnProperty.call(this._sourcesContents, key) ? this._sourcesContents[key] : null;
+	  }, this);
+	};
+
+	/**
+	 * Externalize the source map.
+	 */
+	SourceMapGenerator.prototype.toJSON = function SourceMapGenerator_toJSON() {
+	  var map = {
+	    version: this._version,
+	    sources: this._sources.toArray(),
+	    names: this._names.toArray(),
+	    mappings: this._serializeMappings()
+	  };
+	  if (this._file != null) {
+	    map.file = this._file;
+	  }
+	  if (this._sourceRoot != null) {
+	    map.sourceRoot = this._sourceRoot;
+	  }
+	  if (this._sourcesContents) {
+	    map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot);
+	  }
+
+	  return map;
+	};
+
+	/**
+	 * Render the source map being generated to a string.
+	 */
+	SourceMapGenerator.prototype.toString = function SourceMapGenerator_toString() {
+	  return JSON.stringify(this.toJSON());
+	};
+
+	exports.SourceMapGenerator = SourceMapGenerator;
+
+/***/ },
+/* 29 */
+/***/ function(module, exports, __webpack_require__) {
+
+	/* -*- Mode: js; js-indent-level: 2; -*- */
+	/*
+	 * Copyright 2011 Mozilla Foundation and contributors
+	 * Licensed under the New BSD license. See LICENSE or:
+	 * http://opensource.org/licenses/BSD-3-Clause
+	 *
+	 * Based on the Base 64 VLQ implementation in Closure Compiler:
+	 * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java
+	 *
+	 * Copyright 2011 The Closure Compiler Authors. All rights reserved.
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are
+	 * met:
+	 *
+	 *  * Redistributions of source code must retain the above copyright
+	 *    notice, this list of conditions and the following disclaimer.
+	 *  * Redistributions in binary form must reproduce the above
+	 *    copyright notice, this list of conditions and the following
+	 *    disclaimer in the documentation and/or other materials provided
+	 *    with the distribution.
+	 *  * Neither the name of Google Inc. nor the names of its
+	 *    contributors may be used to endorse or promote products derived
+	 *    from this software without specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+	 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+	 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+	 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+	 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+	 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+	 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+	 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+	 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+	 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+	 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+	 */
+
+	var base64 = __webpack_require__(30);
+
+	// A single base 64 digit can contain 6 bits of data. For the base 64 variable
+	// length quantities we use in the source map spec, the first bit is the sign,
+	// the next four bits are the actual value, and the 6th bit is the
+	// continuation bit. The continuation bit tells us whether there are more
+	// digits in this value following this digit.
+	//
+	//   Continuation
+	//   |    Sign
+	//   |    |
+	//   V    V
+	//   101011
+
+	var VLQ_BASE_SHIFT = 5;
+
+	// binary: 100000
+	var VLQ_BASE = 1 << VLQ_BASE_SHIFT;
+
+	// binary: 011111
+	var VLQ_BASE_MASK = VLQ_BASE - 1;
+
+	// binary: 100000
+	var VLQ_CONTINUATION_BIT = VLQ_BASE;
+
+	/**
+	 * Converts from a two-complement value to a value where the sign bit is
+	 * placed in the least significant bit.  For example, as decimals:
+	 *   1 becomes 2 (10 binary), -1 becomes 3 (11 binary)
+	 *   2 becomes 4 (100 binary), -2 becomes 5 (101 binary)
+	 */
+	function toVLQSigned(aValue) {
+	  return aValue < 0 ? (-aValue << 1) + 1 : (aValue << 1) + 0;
+	}
+
+	/**
+	 * Converts to a two-complement value from a value where the sign bit is
+	 * placed in the least significant bit.  For example, as decimals:
+	 *   2 (10 binary) becomes 1, 3 (11 binary) becomes -1
+	 *   4 (100 binary) becomes 2, 5 (101 binary) becomes -2
+	 */
+	function fromVLQSigned(aValue) {
+	  var isNegative = (aValue & 1) === 1;
+	  var shifted = aValue >> 1;
+	  return isNegative ? -shifted : shifted;
+	}
+
+	/**
+	 * Returns the base 64 VLQ encoded value.
+	 */
+	exports.encode = function base64VLQ_encode(aValue) {
+	  var encoded = "";
+	  var digit;
+
+	  var vlq = toVLQSigned(aValue);
+
+	  do {
+	    digit = vlq & VLQ_BASE_MASK;
+	    vlq >>>= VLQ_BASE_SHIFT;
+	    if (vlq > 0) {
+	      // There are still more digits in this value, so we must make sure the
+	      // continuation bit is marked.
+	      digit |= VLQ_CONTINUATION_BIT;
+	    }
+	    encoded += base64.encode(digit);
+	  } while (vlq > 0);
+
+	  return encoded;
+	};
+
+	/**
+	 * Decodes the next base 64 VLQ value from the given string and returns the
+	 * value and the rest of the string via the out parameter.
+	 */
+	exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) {
+	  var strLen = aStr.length;
+	  var result = 0;
+	  var shift = 0;
+	  var continuation, digit;
+
+	  do {
+	    if (aIndex >= strLen) {
+	      throw new Error("Expected more digits in base 64 VLQ value.");
+	    }
+
+	    digit = base64.decode(aStr.charCodeAt(aIndex++));
+	    if (digit === -1) {
+	      throw new Error("Invalid base64 digit: " + aStr.charAt(aIndex - 1));
+	    }
+
+	    continuation = !!(digit & VLQ_CONTINUATION_BIT);
+	    digit &= VLQ_BASE_MASK;
+	    result = result + (digit << shift);
+	    shift += VLQ_BASE_SHIFT;
+	  } while (continuation);
+
+	  aOutParam.value = fromVLQSigned(result);
+	  aOutParam.rest = aIndex;
+	};
+
+/***/ },
+/* 30 */
+/***/ function(module, exports) {
+
+	/* -*- Mode: js; js-indent-level: 2; -*- */
+	/*
+	 * Copyright 2011 Mozilla Foundation and contributors
+	 * Licensed under the New BSD license. See LICENSE or:
+	 * http://opensource.org/licenses/BSD-3-Clause
+	 */
+
+	var intToCharMap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('');
+
+	/**
+	 * Encode an integer in the range of 0 to 63 to a single base 64 digit.
+	 */
+	exports.encode = function (number) {
+	  if (0 <= number && number < intToCharMap.length) {
+	    return intToCharMap[number];
+	  }
+	  throw new TypeError("Must be between 0 and 63: " + number);
+	};
+
+	/**
+	 * Decode a single base 64 character code digit to an integer. Returns -1 on
+	 * failure.
+	 */
+	exports.decode = function (charCode) {
+	  var bigA = 65; // 'A'
+	  var bigZ = 90; // 'Z'
+
+	  var littleA = 97; // 'a'
+	  var littleZ = 122; // 'z'
+
+	  var zero = 48; // '0'
+	  var nine = 57; // '9'
+
+	  var plus = 43; // '+'
+	  var slash = 47; // '/'
+
+	  var littleOffset = 26;
+	  var numberOffset = 52;
+
+	  // 0 - 25: ABCDEFGHIJKLMNOPQRSTUVWXYZ
+	  if (bigA <= charCode && charCode <= bigZ) {
+	    return charCode - bigA;
+	  }
+
+	  // 26 - 51: abcdefghijklmnopqrstuvwxyz
+	  if (littleA <= charCode && charCode <= littleZ) {
+	    return charCode - littleA + littleOffset;
+	  }
+
+	  // 52 - 61: 0123456789
+	  if (zero <= charCode && charCode <= nine) {
+	    return charCode - zero + numberOffset;
+	  }
+
+	  // 62: +
+	  if (charCode == plus) {
+	    return 62;
+	  }
+
+	  // 63: /
+	  if (charCode == slash) {
+	    return 63;
+	  }
+
+	  // Invalid base64 digit.
+	  return -1;
+	};
+
+/***/ },
+/* 31 */
+/***/ function(module, exports) {
+
+	/* -*- Mode: js; js-indent-level: 2; -*- */
+	/*
+	 * Copyright 2011 Mozilla Foundation and contributors
+	 * Licensed under the New BSD license. See LICENSE or:
+	 * http://opensource.org/licenses/BSD-3-Clause
+	 */
+
+	/**
+	 * This is a helper function for getting values from parameter/options
+	 * objects.
+	 *
+	 * @param args The object we are extracting values from
+	 * @param name The name of the property we are getting.
+	 * @param defaultValue An optional value to return if the property is missing
+	 * from the object. If this is not specified and the property is missing, an
+	 * error will be thrown.
+	 */
+	function getArg(aArgs, aName, aDefaultValue) {
+	  if (aName in aArgs) {
+	    return aArgs[aName];
+	  } else if (arguments.length === 3) {
+	    return aDefaultValue;
+	  } else {
+	    throw new Error('"' + aName + '" is a required argument.');
+	  }
+	}
+	exports.getArg = getArg;
+
+	var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.]*)(?::(\d+))?(\S*)$/;
+	var dataUrlRegexp = /^data:.+\,.+$/;
+
+	function urlParse(aUrl) {
+	  var match = aUrl.match(urlRegexp);
+	  if (!match) {
+	    return null;
+	  }
+	  return {
+	    scheme: match[1],
+	    auth: match[2],
+	    host: match[3],
+	    port: match[4],
+	    path: match[5]
+	  };
+	}
+	exports.urlParse = urlParse;
+
+	function urlGenerate(aParsedUrl) {
+	  var url = '';
+	  if (aParsedUrl.scheme) {
+	    url += aParsedUrl.scheme + ':';
+	  }
+	  url += '//';
+	  if (aParsedUrl.auth) {
+	    url += aParsedUrl.auth + '@';
+	  }
+	  if (aParsedUrl.host) {
+	    url += aParsedUrl.host;
+	  }
+	  if (aParsedUrl.port) {
+	    url += ":" + aParsedUrl.port;
+	  }
+	  if (aParsedUrl.path) {
+	    url += aParsedUrl.path;
+	  }
+	  return url;
+	}
+	exports.urlGenerate = urlGenerate;
+
+	/**
+	 * Normalizes a path, or the path portion of a URL:
+	 *
+	 * - Replaces consecutive slashes with one slash.
+	 * - Removes unnecessary '.' parts.
+	 * - Removes unnecessary '<dir>/..' parts.
+	 *
+	 * Based on code in the Node.js 'path' core module.
+	 *
+	 * @param aPath The path or url to normalize.
+	 */
+	function normalize(aPath) {
+	  var path = aPath;
+	  var url = urlParse(aPath);
+	  if (url) {
+	    if (!url.path) {
+	      return aPath;
+	    }
+	    path = url.path;
+	  }
+	  var isAbsolute = exports.isAbsolute(path);
+
+	  var parts = path.split(/\/+/);
+	  for (var part, up = 0, i = parts.length - 1; i >= 0; i--) {
+	    part = parts[i];
+	    if (part === '.') {
+	      parts.splice(i, 1);
+	    } else if (part === '..') {
+	      up++;
+	    } else if (up > 0) {
+	      if (part === '') {
+	        // The first part is blank if the path is absolute. Trying to go
+	        // above the root is a no-op. Therefore we can remove all '..' parts
+	        // directly after the root.
+	        parts.splice(i + 1, up);
+	        up = 0;
+	      } else {
+	        parts.splice(i, 2);
+	        up--;
+	      }
+	    }
+	  }
+	  path = parts.join('/');
+
+	  if (path === '') {
+	    path = isAbsolute ? '/' : '.';
+	  }
+
+	  if (url) {
+	    url.path = path;
+	    return urlGenerate(url);
+	  }
+	  return path;
+	}
+	exports.normalize = normalize;
+
+	/**
+	 * Joins two paths/URLs.
+	 *
+	 * @param aRoot The root path or URL.
+	 * @param aPath The path or URL to be joined with the root.
+	 *
+	 * - If aPath is a URL or a data URI, aPath is returned, unless aPath is a
+	 *   scheme-relative URL: Then the scheme of aRoot, if any, is prepended
+	 *   first.
+	 * - Otherwise aPath is a path. If aRoot is a URL, then its path portion
+	 *   is updated with the result and aRoot is returned. Otherwise the result
+	 *   is returned.
+	 *   - If aPath is absolute, the result is aPath.
+	 *   - Otherwise the two paths are joined with a slash.
+	 * - Joining for example 'http://' and 'www.example.com' is also supported.
+	 */
+	function join(aRoot, aPath) {
+	  if (aRoot === "") {
+	    aRoot = ".";
+	  }
+	  if (aPath === "") {
+	    aPath = ".";
+	  }
+	  var aPathUrl = urlParse(aPath);
+	  var aRootUrl = urlParse(aRoot);
+	  if (aRootUrl) {
+	    aRoot = aRootUrl.path || '/';
+	  }
+
+	  // `join(foo, '//www.example.org')`
+	  if (aPathUrl && !aPathUrl.scheme) {
+	    if (aRootUrl) {
+	      aPathUrl.scheme = aRootUrl.scheme;
+	    }
+	    return urlGenerate(aPathUrl);
+	  }
+
+	  if (aPathUrl || aPath.match(dataUrlRegexp)) {
+	    return aPath;
+	  }
+
+	  // `join('http://', 'www.example.com')`
+	  if (aRootUrl && !aRootUrl.host && !aRootUrl.path) {
+	    aRootUrl.host = aPath;
+	    return urlGenerate(aRootUrl);
+	  }
+
+	  var joined = aPath.charAt(0) === '/' ? aPath : normalize(aRoot.replace(/\/+$/, '') + '/' + aPath);
+
+	  if (aRootUrl) {
+	    aRootUrl.path = joined;
+	    return urlGenerate(aRootUrl);
+	  }
+	  return joined;
+	}
+	exports.join = join;
+
+	exports.isAbsolute = function (aPath) {
+	  return aPath.charAt(0) === '/' || !!aPath.match(urlRegexp);
+	};
+
+	/**
+	 * Make a path relative to a URL or another path.
+	 *
+	 * @param aRoot The root path or URL.
+	 * @param aPath The path or URL to be made relative to aRoot.
+	 */
+	function relative(aRoot, aPath) {
+	  if (aRoot === "") {
+	    aRoot = ".";
+	  }
+
+	  aRoot = aRoot.replace(/\/$/, '');
+
+	  // It is possible for the path to be above the root. In this case, simply
+	  // checking whether the root is a prefix of the path won't work. Instead, we
+	  // need to remove components from the root one by one, until either we find
+	  // a prefix that fits, or we run out of components to remove.
+	  var level = 0;
+	  while (aPath.indexOf(aRoot + '/') !== 0) {
+	    var index = aRoot.lastIndexOf("/");
+	    if (index < 0) {
+	      return aPath;
+	    }
+
+	    // If the only part of the root that is left is the scheme (i.e. http://,
+	    // file:///, etc.), one or more slashes (/), or simply nothing at all, we
+	    // have exhausted all components, so the path is not relative to the root.
+	    aRoot = aRoot.slice(0, index);
+	    if (aRoot.match(/^([^\/]+:\/)?\/*$/)) {
+	      return aPath;
+	    }
+
+	    ++level;
+	  }
+
+	  // Make sure we add a "../" for each component we removed from the root.
+	  return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1);
+	}
+	exports.relative = relative;
+
+	var supportsNullProto = function () {
+	  var obj = Object.create(null);
+	  return !('__proto__' in obj);
+	}();
+
+	function identity(s) {
+	  return s;
+	}
+
+	/**
+	 * Because behavior goes wacky when you set `__proto__` on objects, we
+	 * have to prefix all the strings in our set with an arbitrary character.
+	 *
+	 * See https://github.com/mozilla/source-map/pull/31 and
+	 * https://github.com/mozilla/source-map/issues/30
+	 *
+	 * @param String aStr
+	 */
+	function toSetString(aStr) {
+	  if (isProtoString(aStr)) {
+	    return '$' + aStr;
+	  }
+
+	  return aStr;
+	}
+	exports.toSetString = supportsNullProto ? identity : toSetString;
+
+	function fromSetString(aStr) {
+	  if (isProtoString(aStr)) {
+	    return aStr.slice(1);
+	  }
+
+	  return aStr;
+	}
+	exports.fromSetString = supportsNullProto ? identity : fromSetString;
+
+	function isProtoString(s) {
+	  if (!s) {
+	    return false;
+	  }
+
+	  var length = s.length;
+
+	  if (length < 9 /* "__proto__".length */) {
+	      return false;
+	    }
+
+	  if (s.charCodeAt(length - 1) !== 95 /* '_' */ || s.charCodeAt(length - 2) !== 95 /* '_' */ || s.charCodeAt(length - 3) !== 111 /* 'o' */ || s.charCodeAt(length - 4) !== 116 /* 't' */ || s.charCodeAt(length - 5) !== 111 /* 'o' */ || s.charCodeAt(length - 6) !== 114 /* 'r' */ || s.charCodeAt(length - 7) !== 112 /* 'p' */ || s.charCodeAt(length - 8) !== 95 /* '_' */ || s.charCodeAt(length - 9) !== 95 /* '_' */) {
+	      return false;
+	    }
+
+	  for (var i = length - 10; i >= 0; i--) {
+	    if (s.charCodeAt(i) !== 36 /* '$' */) {
+	        return false;
+	      }
+	  }
+
+	  return true;
+	}
+
+	/**
+	 * Comparator between two mappings where the original positions are compared.
+	 *
+	 * Optionally pass in `true` as `onlyCompareGenerated` to consider two
+	 * mappings with the same original source/line/column, but different generated
+	 * line and column the same. Useful when searching for a mapping with a
+	 * stubbed out mapping.
+	 */
+	function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) {
+	  var cmp = mappingA.source - mappingB.source;
+	  if (cmp !== 0) {
+	    return cmp;
+	  }
+
+	  cmp = mappingA.originalLine - mappingB.originalLine;
+	  if (cmp !== 0) {
+	    return cmp;
+	  }
+
+	  cmp = mappingA.originalColumn - mappingB.originalColumn;
+	  if (cmp !== 0 || onlyCompareOriginal) {
+	    return cmp;
+	  }
+
+	  cmp = mappingA.generatedColumn - mappingB.generatedColumn;
+	  if (cmp !== 0) {
+	    return cmp;
+	  }
+
+	  cmp = mappingA.generatedLine - mappingB.generatedLine;
+	  if (cmp !== 0) {
+	    return cmp;
+	  }
+
+	  return mappingA.name - mappingB.name;
+	}
+	exports.compareByOriginalPositions = compareByOriginalPositions;
+
+	/**
+	 * Comparator between two mappings with deflated source and name indices where
+	 * the generated positions are compared.
+	 *
+	 * Optionally pass in `true` as `onlyCompareGenerated` to consider two
+	 * mappings with the same generated line and column, but different
+	 * source/name/original line and column the same. Useful when searching for a
+	 * mapping with a stubbed out mapping.
+	 */
+	function compareByGeneratedPositionsDeflated(mappingA, mappingB, onlyCompareGenerated) {
+	  var cmp = mappingA.generatedLine - mappingB.generatedLine;
+	  if (cmp !== 0) {
+	    return cmp;
+	  }
+
+	  cmp = mappingA.generatedColumn - mappingB.generatedColumn;
+	  if (cmp !== 0 || onlyCompareGenerated) {
+	    return cmp;
+	  }
+
+	  cmp = mappingA.source - mappingB.source;
+	  if (cmp !== 0) {
+	    return cmp;
+	  }
+
+	  cmp = mappingA.originalLine - mappingB.originalLine;
+	  if (cmp !== 0) {
+	    return cmp;
+	  }
+
+	  cmp = mappingA.originalColumn - mappingB.originalColumn;
+	  if (cmp !== 0) {
+	    return cmp;
+	  }
+
+	  return mappingA.name - mappingB.name;
+	}
+	exports.compareByGeneratedPositionsDeflated = compareByGeneratedPositionsDeflated;
+
+	function strcmp(aStr1, aStr2) {
+	  if (aStr1 === aStr2) {
+	    return 0;
+	  }
+
+	  if (aStr1 > aStr2) {
+	    return 1;
+	  }
+
+	  return -1;
+	}
+
+	/**
+	 * Comparator between two mappings with inflated source and name strings where
+	 * the generated positions are compared.
+	 */
+	function compareByGeneratedPositionsInflated(mappingA, mappingB) {
+	  var cmp = mappingA.generatedLine - mappingB.generatedLine;
+	  if (cmp !== 0) {
+	    return cmp;
+	  }
+
+	  cmp = mappingA.generatedColumn - mappingB.generatedColumn;
+	  if (cmp !== 0) {
+	    return cmp;
+	  }
+
+	  cmp = strcmp(mappingA.source, mappingB.source);
+	  if (cmp !== 0) {
+	    return cmp;
+	  }
+
+	  cmp = mappingA.originalLine - mappingB.originalLine;
+	  if (cmp !== 0) {
+	    return cmp;
+	  }
+
+	  cmp = mappingA.originalColumn - mappingB.originalColumn;
+	  if (cmp !== 0) {
+	    return cmp;
+	  }
+
+	  return strcmp(mappingA.name, mappingB.name);
+	}
+	exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated;
+
+/***/ },
+/* 32 */
+/***/ function(module, exports, __webpack_require__) {
+
+	/* -*- Mode: js; js-indent-level: 2; -*- */
+	/*
+	 * Copyright 2011 Mozilla Foundation and contributors
+	 * Licensed under the New BSD license. See LICENSE or:
+	 * http://opensource.org/licenses/BSD-3-Clause
+	 */
+
+	var util = __webpack_require__(31);
+	var has = Object.prototype.hasOwnProperty;
+	var hasNativeMap = typeof Map !== "undefined";
+
+	/**
+	 * A data structure which is a combination of an array and a set. Adding a new
+	 * member is O(1), testing for membership is O(1), and finding the index of an
+	 * element is O(1). Removing elements from the set is not supported. Only
+	 * strings are supported for membership.
+	 */
+	function ArraySet() {
+	  this._array = [];
+	  this._set = hasNativeMap ? new Map() : Object.create(null);
+	}
+
+	/**
+	 * Static method for creating ArraySet instances from an existing array.
+	 */
+	ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) {
+	  var set = new ArraySet();
+	  for (var i = 0, len = aArray.length; i < len; i++) {
+	    set.add(aArray[i], aAllowDuplicates);
+	  }
+	  return set;
+	};
+
+	/**
+	 * Return how many unique items are in this ArraySet. If duplicates have been
+	 * added, than those do not count towards the size.
+	 *
+	 * @returns Number
+	 */
+	ArraySet.prototype.size = function ArraySet_size() {
+	  return hasNativeMap ? this._set.size : Object.getOwnPropertyNames(this._set).length;
+	};
+
+	/**
+	 * Add the given string to this set.
+	 *
+	 * @param String aStr
+	 */
+	ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) {
+	  var sStr = hasNativeMap ? aStr : util.toSetString(aStr);
+	  var isDuplicate = hasNativeMap ? this.has(aStr) : has.call(this._set, sStr);
+	  var idx = this._array.length;
+	  if (!isDuplicate || aAllowDuplicates) {
+	    this._array.push(aStr);
+	  }
+	  if (!isDuplicate) {
+	    if (hasNativeMap) {
+	      this._set.set(aStr, idx);
+	    } else {
+	      this._set[sStr] = idx;
+	    }
+	  }
+	};
+
+	/**
+	 * Is the given string a member of this set?
+	 *
+	 * @param String aStr
+	 */
+	ArraySet.prototype.has = function ArraySet_has(aStr) {
+	  if (hasNativeMap) {
+	    return this._set.has(aStr);
+	  } else {
+	    var sStr = util.toSetString(aStr);
+	    return has.call(this._set, sStr);
+	  }
+	};
+
+	/**
+	 * What is the index of the given string in the array?
+	 *
+	 * @param String aStr
+	 */
+	ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) {
+	  if (hasNativeMap) {
+	    var idx = this._set.get(aStr);
+	    if (idx >= 0) {
+	      return idx;
+	    }
+	  } else {
+	    var sStr = util.toSetString(aStr);
+	    if (has.call(this._set, sStr)) {
+	      return this._set[sStr];
+	    }
+	  }
+
+	  throw new Error('"' + aStr + '" is not in the set.');
+	};
+
+	/**
+	 * What is the element at the given index?
+	 *
+	 * @param Number aIdx
+	 */
+	ArraySet.prototype.at = function ArraySet_at(aIdx) {
+	  if (aIdx >= 0 && aIdx < this._array.length) {
+	    return this._array[aIdx];
+	  }
+	  throw new Error('No element indexed by ' + aIdx);
+	};
+
+	/**
+	 * Returns the array representation of this set (which has the proper indices
+	 * indicated by indexOf). Note that this is a copy of the internal array used
+	 * for storing the members so that no one can mess with internal state.
+	 */
+	ArraySet.prototype.toArray = function ArraySet_toArray() {
+	  return this._array.slice();
+	};
+
+	exports.ArraySet = ArraySet;
+
+/***/ },
+/* 33 */
+/***/ function(module, exports, __webpack_require__) {
+
+	/* -*- Mode: js; js-indent-level: 2; -*- */
+	/*
+	 * Copyright 2014 Mozilla Foundation and contributors
+	 * Licensed under the New BSD license. See LICENSE or:
+	 * http://opensource.org/licenses/BSD-3-Clause
+	 */
+
+	var util = __webpack_require__(31);
+
+	/**
+	 * Determine whether mappingB is after mappingA with respect to generated
+	 * position.
+	 */
+	function generatedPositionAfter(mappingA, mappingB) {
+	  // Optimized for most common case
+	  var lineA = mappingA.generatedLine;
+	  var lineB = mappingB.generatedLine;
+	  var columnA = mappingA.generatedColumn;
+	  var columnB = mappingB.generatedColumn;
+	  return lineB > lineA || lineB == lineA && columnB >= columnA || util.compareByGeneratedPositionsInflated(mappingA, mappingB) <= 0;
+	}
+
+	/**
+	 * A data structure to provide a sorted view of accumulated mappings in a
+	 * performance conscious manner. It trades a neglibable overhead in general
+	 * case for a large speedup in case of mappings being added in order.
+	 */
+	function MappingList() {
+	  this._array = [];
+	  this._sorted = true;
+	  // Serves as infimum
+	  this._last = { generatedLine: -1, generatedColumn: 0 };
+	}
+
+	/**
+	 * Iterate through internal items. This method takes the same arguments that
+	 * `Array.prototype.forEach` takes.
+	 *
+	 * NOTE: The order of the mappings is NOT guaranteed.
+	 */
+	MappingList.prototype.unsortedForEach = function MappingList_forEach(aCallback, aThisArg) {
+	  this._array.forEach(aCallback, aThisArg);
+	};
+
+	/**
+	 * Add the given source mapping.
+	 *
+	 * @param Object aMapping
+	 */
+	MappingList.prototype.add = function MappingList_add(aMapping) {
+	  if (generatedPositionAfter(this._last, aMapping)) {
+	    this._last = aMapping;
+	    this._array.push(aMapping);
+	  } else {
+	    this._sorted = false;
+	    this._array.push(aMapping);
+	  }
+	};
+
+	/**
+	 * Returns the flat, sorted array of mappings. The mappings are sorted by
+	 * generated position.
+	 *
+	 * WARNING: This method returns internal data without copying, for
+	 * performance. The return value must NOT be mutated, and should be treated as
+	 * an immutable borrow. If you want to take ownership, you must make your own
+	 * copy.
+	 */
+	MappingList.prototype.toArray = function MappingList_toArray() {
+	  if (!this._sorted) {
+	    this._array.sort(util.compareByGeneratedPositionsInflated);
+	    this._sorted = true;
+	  }
+	  return this._array;
+	};
+
+	exports.MappingList = MappingList;
+
+/***/ },
+/* 34 */
+/***/ function(module, exports, __webpack_require__) {
+
+	/* -*- Mode: js; js-indent-level: 2; -*- */
+	/*
+	 * Copyright 2011 Mozilla Foundation and contributors
+	 * Licensed under the New BSD license. See LICENSE or:
+	 * http://opensource.org/licenses/BSD-3-Clause
+	 */
+
+	var util = __webpack_require__(31);
+	var binarySearch = __webpack_require__(35);
+	var ArraySet = __webpack_require__(32).ArraySet;
+	var base64VLQ = __webpack_require__(29);
+	var quickSort = __webpack_require__(36).quickSort;
+
+	function SourceMapConsumer(aSourceMap) {
+	  var sourceMap = aSourceMap;
+	  if (typeof aSourceMap === 'string') {
+	    sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, ''));
+	  }
+
+	  return sourceMap.sections != null ? new IndexedSourceMapConsumer(sourceMap) : new BasicSourceMapConsumer(sourceMap);
+	}
+
+	SourceMapConsumer.fromSourceMap = function (aSourceMap) {
+	  return BasicSourceMapConsumer.fromSourceMap(aSourceMap);
+	};
+
+	/**
+	 * The version of the source mapping spec that we are consuming.
+	 */
+	SourceMapConsumer.prototype._version = 3;
+
+	// `__generatedMappings` and `__originalMappings` are arrays that hold the
+	// parsed mapping coordinates from the source map's "mappings" attribute. They
+	// are lazily instantiated, accessed via the `_generatedMappings` and
+	// `_originalMappings` getters respectively, and we only parse the mappings
+	// and create these arrays once queried for a source location. We jump through
+	// these hoops because there can be many thousands of mappings, and parsing
+	// them is expensive, so we only want to do it if we must.
+	//
+	// Each object in the arrays is of the form:
+	//
+	//     {
+	//       generatedLine: The line number in the generated code,
+	//       generatedColumn: The column number in the generated code,
+	//       source: The path to the original source file that generated this
+	//               chunk of code,
+	//       originalLine: The line number in the original source that
+	//                     corresponds to this chunk of generated code,
+	//       originalColumn: The column number in the original source that
+	//                       corresponds to this chunk of generated code,
+	//       name: The name of the original symbol which generated this chunk of
+	//             code.
+	//     }
+	//
+	// All properties except for `generatedLine` and `generatedColumn` can be
+	// `null`.
+	//
+	// `_generatedMappings` is ordered by the generated positions.
+	//
+	// `_originalMappings` is ordered by the original positions.
+
+	SourceMapConsumer.prototype.__generatedMappings = null;
+	Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', {
+	  get: function () {
+	    if (!this.__generatedMappings) {
+	      this._parseMappings(this._mappings, this.sourceRoot);
+	    }
+
+	    return this.__generatedMappings;
+	  }
+	});
+
+	SourceMapConsumer.prototype.__originalMappings = null;
+	Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', {
+	  get: function () {
+	    if (!this.__originalMappings) {
+	      this._parseMappings(this._mappings, this.sourceRoot);
+	    }
+
+	    return this.__originalMappings;
+	  }
+	});
+
+	SourceMapConsumer.prototype._charIsMappingSeparator = function SourceMapConsumer_charIsMappingSeparator(aStr, index) {
+	  var c = aStr.charAt(index);
+	  return c === ";" || c === ",";
+	};
+
+	/**
+	 * Parse the mappings in a string in to a data structure which we can easily
+	 * query (the ordered arrays in the `this.__generatedMappings` and
+	 * `this.__originalMappings` properties).
+	 */
+	SourceMapConsumer.prototype._parseMappings = function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {
+	  throw new Error("Subclasses must implement _parseMappings");
+	};
+
+	SourceMapConsumer.GENERATED_ORDER = 1;
+	SourceMapConsumer.ORIGINAL_ORDER = 2;
+
+	SourceMapConsumer.GREATEST_LOWER_BOUND = 1;
+	SourceMapConsumer.LEAST_UPPER_BOUND = 2;
+
+	/**
+	 * Iterate over each mapping between an original source/line/column and a
+	 * generated line/column in this source map.
+	 *
+	 * @param Function aCallback
+	 *        The function that is called with each mapping.
+	 * @param Object aContext
+	 *        Optional. If specified, this object will be the value of `this` every
+	 *        time that `aCallback` is called.
+	 * @param aOrder
+	 *        Either `SourceMapConsumer.GENERATED_ORDER` or
+	 *        `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to
+	 *        iterate over the mappings sorted by the generated file's line/column
+	 *        order or the original's source/line/column order, respectively. Defaults to
+	 *        `SourceMapConsumer.GENERATED_ORDER`.
+	 */
+	SourceMapConsumer.prototype.eachMapping = function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) {
+	  var context = aContext || null;
+	  var order = aOrder || SourceMapConsumer.GENERATED_ORDER;
+
+	  var mappings;
+	  switch (order) {
+	    case SourceMapConsumer.GENERATED_ORDER:
+	      mappings = this._generatedMappings;
+	      break;
+	    case SourceMapConsumer.ORIGINAL_ORDER:
+	      mappings = this._originalMappings;
+	      break;
+	    default:
+	      throw new Error("Unknown order of iteration.");
+	  }
+
+	  var sourceRoot = this.sourceRoot;
+	  mappings.map(function (mapping) {
+	    var source = mapping.source === null ? null : this._sources.at(mapping.source);
+	    if (source != null && sourceRoot != null) {
+	      source = util.join(sourceRoot, source);
+	    }
+	    return {
+	      source: source,
+	      generatedLine: mapping.generatedLine,
+	      generatedColumn: mapping.generatedColumn,
+	      originalLine: mapping.originalLine,
+	      originalColumn: mapping.originalColumn,
+	      name: mapping.name === null ? null : this._names.at(mapping.name)
+	    };
+	  }, this).forEach(aCallback, context);
+	};
+
+	/**
+	 * Returns all generated line and column information for the original source,
+	 * line, and column provided. If no column is provided, returns all mappings
+	 * corresponding to a either the line we are searching for or the next
+	 * closest line that has any mappings. Otherwise, returns all mappings
+	 * corresponding to the given line and either the column we are searching for
+	 * or the next closest column that has any offsets.
+	 *
+	 * The only argument is an object with the following properties:
+	 *
+	 *   - source: The filename of the original source.
+	 *   - line: The line number in the original source.
+	 *   - column: Optional. the column number in the original source.
+	 *
+	 * and an array of objects is returned, each with the following properties:
+	 *
+	 *   - line: The line number in the generated source, or null.
+	 *   - column: The column number in the generated source, or null.
+	 */
+	SourceMapConsumer.prototype.allGeneratedPositionsFor = function SourceMapConsumer_allGeneratedPositionsFor(aArgs) {
+	  var line = util.getArg(aArgs, 'line');
+
+	  // When there is no exact match, BasicSourceMapConsumer.prototype._findMapping
+	  // returns the index of the closest mapping less than the needle. By
+	  // setting needle.originalColumn to 0, we thus find the last mapping for
+	  // the given line, provided such a mapping exists.
+	  var needle = {
+	    source: util.getArg(aArgs, 'source'),
+	    originalLine: line,
+	    originalColumn: util.getArg(aArgs, 'column', 0)
+	  };
+
+	  if (this.sourceRoot != null) {
+	    needle.source = util.relative(this.sourceRoot, needle.source);
+	  }
+	  if (!this._sources.has(needle.source)) {
+	    return [];
+	  }
+	  needle.source = this._sources.indexOf(needle.source);
+
+	  var mappings = [];
+
+	  var index = this._findMapping(needle, this._originalMappings, "originalLine", "originalColumn", util.compareByOriginalPositions, binarySearch.LEAST_UPPER_BOUND);
+	  if (index >= 0) {
+	    var mapping = this._originalMappings[index];
+
+	    if (aArgs.column === undefined) {
+	      var originalLine = mapping.originalLine;
+
+	      // Iterate until either we run out of mappings, or we run into
+	      // a mapping for a different line than the one we found. Since
+	      // mappings are sorted, this is guaranteed to find all mappings for
+	      // the line we found.
+	      while (mapping && mapping.originalLine === originalLine) {
+	        mappings.push({
+	          line: util.getArg(mapping, 'generatedLine', null),
+	          column: util.getArg(mapping, 'generatedColumn', null),
+	          lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)
+	        });
+
+	        mapping = this._originalMappings[++index];
+	      }
+	    } else {
+	      var originalColumn = mapping.originalColumn;
+
+	      // Iterate until either we run out of mappings, or we run into
+	      // a mapping for a different line than the one we were searching for.
+	      // Since mappings are sorted, this is guaranteed to find all mappings for
+	      // the line we are searching for.
+	      while (mapping && mapping.originalLine === line && mapping.originalColumn == originalColumn) {
+	        mappings.push({
+	          line: util.getArg(mapping, 'generatedLine', null),
+	          column: util.getArg(mapping, 'generatedColumn', null),
+	          lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)
+	        });
+
+	        mapping = this._originalMappings[++index];
+	      }
+	    }
+	  }
+
+	  return mappings;
+	};
+
+	exports.SourceMapConsumer = SourceMapConsumer;
+
+	/**
+	 * A BasicSourceMapConsumer instance represents a parsed source map which we can
+	 * query for information about the original file positions by giving it a file
+	 * position in the generated source.
+	 *
+	 * The only parameter is the raw source map (either as a JSON string, or
+	 * already parsed to an object). According to the spec, source maps have the
+	 * following attributes:
+	 *
+	 *   - version: Which version of the source map spec this map is following.
+	 *   - sources: An array of URLs to the original source files.
+	 *   - names: An array of identifiers which can be referrenced by individual mappings.
+	 *   - sourceRoot: Optional. The URL root from which all sources are relative.
+	 *   - sourcesContent: Optional. An array of contents of the original source files.
+	 *   - mappings: A string of base64 VLQs which contain the actual mappings.
+	 *   - file: Optional. The generated file this source map is associated with.
+	 *
+	 * Here is an example source map, taken from the source map spec[0]:
+	 *
+	 *     {
+	 *       version : 3,
+	 *       file: "out.js",
+	 *       sourceRoot : "",
+	 *       sources: ["foo.js", "bar.js"],
+	 *       names: ["src", "maps", "are", "fun"],
+	 *       mappings: "AA,AB;;ABCDE;"
+	 *     }
+	 *
+	 * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1#
+	 */
+	function BasicSourceMapConsumer(aSourceMap) {
+	  var sourceMap = aSourceMap;
+	  if (typeof aSourceMap === 'string') {
+	    sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, ''));
+	  }
+
+	  var version = util.getArg(sourceMap, 'version');
+	  var sources = util.getArg(sourceMap, 'sources');
+	  // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which
+	  // requires the array) to play nice here.
+	  var names = util.getArg(sourceMap, 'names', []);
+	  var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null);
+	  var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null);
+	  var mappings = util.getArg(sourceMap, 'mappings');
+	  var file = util.getArg(sourceMap, 'file', null);
+
+	  // Once again, Sass deviates from the spec and supplies the version as a
+	  // string rather than a number, so we use loose equality checking here.
+	  if (version != this._version) {
+	    throw new Error('Unsupported version: ' + version);
+	  }
+
+	  sources = sources.map(String)
+	  // Some source maps produce relative source paths like "./foo.js" instead of
+	  // "foo.js".  Normalize these first so that future comparisons will succeed.
+	  // See bugzil.la/1090768.
+	  .map(util.normalize)
+	  // Always ensure that absolute sources are internally stored relative to
+	  // the source root, if the source root is absolute. Not doing this would
+	  // be particularly problematic when the source root is a prefix of the
+	  // source (valid, but why??). See github issue #199 and bugzil.la/1188982.
+	  .map(function (source) {
+	    return sourceRoot && util.isAbsolute(sourceRoot) && util.isAbsolute(source) ? util.relative(sourceRoot, source) : source;
+	  });
+
+	  // Pass `true` below to allow duplicate names and sources. While source maps
+	  // are intended to be compressed and deduplicated, the TypeScript compiler
+	  // sometimes generates source maps with duplicates in them. See Github issue
+	  // #72 and bugzil.la/889492.
+	  this._names = ArraySet.fromArray(names.map(String), true);
+	  this._sources = ArraySet.fromArray(sources, true);
+
+	  this.sourceRoot = sourceRoot;
+	  this.sourcesContent = sourcesContent;
+	  this._mappings = mappings;
+	  this.file = file;
+	}
+
+	BasicSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype);
+	BasicSourceMapConsumer.prototype.consumer = SourceMapConsumer;
+
+	/**
+	 * Create a BasicSourceMapConsumer from a SourceMapGenerator.
+	 *
+	 * @param SourceMapGenerator aSourceMap
+	 *        The source map that will be consumed.
+	 * @returns BasicSourceMapConsumer
+	 */
+	BasicSourceMapConsumer.fromSourceMap = function SourceMapConsumer_fromSourceMap(aSourceMap) {
+	  var smc = Object.create(BasicSourceMapConsumer.prototype);
+
+	  var names = smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true);
+	  var sources = smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true);
+	  smc.sourceRoot = aSourceMap._sourceRoot;
+	  smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(), smc.sourceRoot);
+	  smc.file = aSourceMap._file;
+
+	  // Because we are modifying the entries (by converting string sources and
+	  // names to indices into the sources and names ArraySets), we have to make
+	  // a copy of the entry or else bad things happen. Shared mutable state
+	  // strikes again! See github issue #191.
+
+	  var generatedMappings = aSourceMap._mappings.toArray().slice();
+	  var destGeneratedMappings = smc.__generatedMappings = [];
+	  var destOriginalMappings = smc.__originalMappings = [];
+
+	  for (var i = 0, length = generatedMappings.length; i < length; i++) {
+	    var srcMapping = generatedMappings[i];
+	    var destMapping = new Mapping();
+	    destMapping.generatedLine = srcMapping.generatedLine;
+	    destMapping.generatedColumn = srcMapping.generatedColumn;
+
+	    if (srcMapping.source) {
+	      destMapping.source = sources.indexOf(srcMapping.source);
+	      destMapping.originalLine = srcMapping.originalLine;
+	      destMapping.originalColumn = srcMapping.originalColumn;
+
+	      if (srcMapping.name) {
+	        destMapping.name = names.indexOf(srcMapping.name);
+	      }
+
+	      destOriginalMappings.push(destMapping);
+	    }
+
+	    destGeneratedMappings.push(destMapping);
+	  }
+
+	  quickSort(smc.__originalMappings, util.compareByOriginalPositions);
+
+	  return smc;
+	};
+
+	/**
+	 * The version of the source mapping spec that we are consuming.
+	 */
+	BasicSourceMapConsumer.prototype._version = 3;
+
+	/**
+	 * The list of original sources.
+	 */
+	Object.defineProperty(BasicSourceMapConsumer.prototype, 'sources', {
+	  get: function () {
+	    return this._sources.toArray().map(function (s) {
+	      return this.sourceRoot != null ? util.join(this.sourceRoot, s) : s;
+	    }, this);
+	  }
+	});
+
+	/**
+	 * Provide the JIT with a nice shape / hidden class.
+	 */
+	function Mapping() {
+	  this.generatedLine = 0;
+	  this.generatedColumn = 0;
+	  this.source = null;
+	  this.originalLine = null;
+	  this.originalColumn = null;
+	  this.name = null;
+	}
+
+	/**
+	 * Parse the mappings in a string in to a data structure which we can easily
+	 * query (the ordered arrays in the `this.__generatedMappings` and
+	 * `this.__originalMappings` properties).
+	 */
+	BasicSourceMapConsumer.prototype._parseMappings = function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {
+	  var generatedLine = 1;
+	  var previousGeneratedColumn = 0;
+	  var previousOriginalLine = 0;
+	  var previousOriginalColumn = 0;
+	  var previousSource = 0;
+	  var previousName = 0;
+	  var length = aStr.length;
+	  var index = 0;
+	  var cachedSegments = {};
+	  var temp = {};
+	  var originalMappings = [];
+	  var generatedMappings = [];
+	  var mapping, str, segment, end, value;
+
+	  while (index < length) {
+	    if (aStr.charAt(index) === ';') {
+	      generatedLine++;
+	      index++;
+	      previousGeneratedColumn = 0;
+	    } else if (aStr.charAt(index) === ',') {
+	      index++;
+	    } else {
+	      mapping = new Mapping();
+	      mapping.generatedLine = generatedLine;
+
+	      // Because each offset is encoded relative to the previous one,
+	      // many segments often have the same encoding. We can exploit this
+	      // fact by caching the parsed variable length fields of each segment,
+	      // allowing us to avoid a second parse if we encounter the same
+	      // segment again.
+	      for (end = index; end < length; end++) {
+	        if (this._charIsMappingSeparator(aStr, end)) {
+	          break;
+	        }
+	      }
+	      str = aStr.slice(index, end);
+
+	      segment = cachedSegments[str];
+	      if (segment) {
+	        index += str.length;
+	      } else {
+	        segment = [];
+	        while (index < end) {
+	          base64VLQ.decode(aStr, index, temp);
+	          value = temp.value;
+	          index = temp.rest;
+	          segment.push(value);
+	        }
+
+	        if (segment.length === 2) {
+	          throw new Error('Found a source, but no line and column');
+	        }
+
+	        if (segment.length === 3) {
+	          throw new Error('Found a source and line, but no column');
+	        }
+
+	        cachedSegments[str] = segment;
+	      }
+
+	      // Generated column.
+	      mapping.generatedColumn = previousGeneratedColumn + segment[0];
+	      previousGeneratedColumn = mapping.generatedColumn;
+
+	      if (segment.length > 1) {
+	        // Original source.
+	        mapping.source = previousSource + segment[1];
+	        previousSource += segment[1];
+
+	        // Original line.
+	        mapping.originalLine = previousOriginalLine + segment[2];
+	        previousOriginalLine = mapping.originalLine;
+	        // Lines are stored 0-based
+	        mapping.originalLine += 1;
+
+	        // Original column.
+	        mapping.originalColumn = previousOriginalColumn + segment[3];
+	        previousOriginalColumn = mapping.originalColumn;
+
+	        if (segment.length > 4) {
+	          // Original name.
+	          mapping.name = previousName + segment[4];
+	          previousName += segment[4];
+	        }
+	      }
+
+	      generatedMappings.push(mapping);
+	      if (typeof mapping.originalLine === 'number') {
+	        originalMappings.push(mapping);
+	      }
+	    }
+	  }
+
+	  quickSort(generatedMappings, util.compareByGeneratedPositionsDeflated);
+	  this.__generatedMappings = generatedMappings;
+
+	  quickSort(originalMappings, util.compareByOriginalPositions);
+	  this.__originalMappings = originalMappings;
+	};
+
+	/**
+	 * Find the mapping that best matches the hypothetical "needle" mapping that
+	 * we are searching for in the given "haystack" of mappings.
+	 */
+	BasicSourceMapConsumer.prototype._findMapping = function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, aColumnName, aComparator, aBias) {
+	  // To return the position we are searching for, we must first find the
+	  // mapping for the given position and then return the opposite position it
+	  // points to. Because the mappings are sorted, we can use binary search to
+	  // find the best mapping.
+
+	  if (aNeedle[aLineName] <= 0) {
+	    throw new TypeError('Line must be greater than or equal to 1, got ' + aNeedle[aLineName]);
+	  }
+	  if (aNeedle[aColumnName] < 0) {
+	    throw new TypeError('Column must be greater than or equal to 0, got ' + aNeedle[aColumnName]);
+	  }
+
+	  return binarySearch.search(aNeedle, aMappings, aComparator, aBias);
+	};
+
+	/**
+	 * Compute the last column for each generated mapping. The last column is
+	 * inclusive.
+	 */
+	BasicSourceMapConsumer.prototype.computeColumnSpans = function SourceMapConsumer_computeColumnSpans() {
+	  for (var index = 0; index < this._generatedMappings.length; ++index) {
+	    var mapping = this._generatedMappings[index];
+
+	    // Mappings do not contain a field for the last generated columnt. We
+	    // can come up with an optimistic estimate, however, by assuming that
+	    // mappings are contiguous (i.e. given two consecutive mappings, the
+	    // first mapping ends where the second one starts).
+	    if (index + 1 < this._generatedMappings.length) {
+	      var nextMapping = this._generatedMappings[index + 1];
+
+	      if (mapping.generatedLine === nextMapping.generatedLine) {
+	        mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1;
+	        continue;
+	      }
+	    }
+
+	    // The last mapping for each line spans the entire line.
+	    mapping.lastGeneratedColumn = Infinity;
+	  }
+	};
+
+	/**
+	 * Returns the original source, line, and column information for the generated
+	 * source's line and column positions provided. The only argument is an object
+	 * with the following properties:
+	 *
+	 *   - line: The line number in the generated source.
+	 *   - column: The column number in the generated source.
+	 *   - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or
+	 *     'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the
+	 *     closest element that is smaller than or greater than the one we are
+	 *     searching for, respectively, if the exact element cannot be found.
+	 *     Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'.
+	 *
+	 * and an object is returned with the following properties:
+	 *
+	 *   - source: The original source file, or null.
+	 *   - line: The line number in the original source, or null.
+	 *   - column: The column number in the original source, or null.
+	 *   - name: The original identifier, or null.
+	 */
+	BasicSourceMapConsumer.prototype.originalPositionFor = function SourceMapConsumer_originalPositionFor(aArgs) {
+	  var needle = {
+	    generatedLine: util.getArg(aArgs, 'line'),
+	    generatedColumn: util.getArg(aArgs, 'column')
+	  };
+
+	  var index = this._findMapping(needle, this._generatedMappings, "generatedLine", "generatedColumn", util.compareByGeneratedPositionsDeflated, util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND));
+
+	  if (index >= 0) {
+	    var mapping = this._generatedMappings[index];
+
+	    if (mapping.generatedLine === needle.generatedLine) {
+	      var source = util.getArg(mapping, 'source', null);
+	      if (source !== null) {
+	        source = this._sources.at(source);
+	        if (this.sourceRoot != null) {
+	          source = util.join(this.sourceRoot, source);
+	        }
+	      }
+	      var name = util.getArg(mapping, 'name', null);
+	      if (name !== null) {
+	        name = this._names.at(name);
+	      }
+	      return {
+	        source: source,
+	        line: util.getArg(mapping, 'originalLine', null),
+	        column: util.getArg(mapping, 'originalColumn', null),
+	        name: name
+	      };
+	    }
+	  }
+
+	  return {
+	    source: null,
+	    line: null,
+	    column: null,
+	    name: null
+	  };
+	};
+
+	/**
+	 * Return true if we have the source content for every source in the source
+	 * map, false otherwise.
+	 */
+	BasicSourceMapConsumer.prototype.hasContentsOfAllSources = function BasicSourceMapConsumer_hasContentsOfAllSources() {
+	  if (!this.sourcesContent) {
+	    return false;
+	  }
+	  return this.sourcesContent.length >= this._sources.size() && !this.sourcesContent.some(function (sc) {
+	    return sc == null;
+	  });
+	};
+
+	/**
+	 * Returns the original source content. The only argument is the url of the
+	 * original source file. Returns null if no original source content is
+	 * available.
+	 */
+	BasicSourceMapConsumer.prototype.sourceContentFor = function SourceMapConsumer_sourceContentFor(aSource, nullOnMissing) {
+	  if (!this.sourcesContent) {
+	    return null;
+	  }
+
+	  if (this.sourceRoot != null) {
+	    aSource = util.relative(this.sourceRoot, aSource);
+	  }
+
+	  if (this._sources.has(aSource)) {
+	    return this.sourcesContent[this._sources.indexOf(aSource)];
+	  }
+
+	  var url;
+	  if (this.sourceRoot != null && (url = util.urlParse(this.sourceRoot))) {
+	    // XXX: file:// URIs and absolute paths lead to unexpected behavior for
+	    // many users. We can help them out when they expect file:// URIs to
+	    // behave like it would if they were running a local HTTP server. See
+	    // https://bugzilla.mozilla.org/show_bug.cgi?id=885597.
+	    var fileUriAbsPath = aSource.replace(/^file:\/\//, "");
+	    if (url.scheme == "file" && this._sources.has(fileUriAbsPath)) {
+	      return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)];
+	    }
+
+	    if ((!url.path || url.path == "/") && this._sources.has("/" + aSource)) {
+	      return this.sourcesContent[this._sources.indexOf("/" + aSource)];
+	    }
+	  }
+
+	  // This function is used recursively from
+	  // IndexedSourceMapConsumer.prototype.sourceContentFor. In that case, we
+	  // don't want to throw if we can't find the source - we just want to
+	  // return null, so we provide a flag to exit gracefully.
+	  if (nullOnMissing) {
+	    return null;
+	  } else {
+	    throw new Error('"' + aSource + '" is not in the SourceMap.');
+	  }
+	};
+
+	/**
+	 * Returns the generated line and column information for the original source,
+	 * line, and column positions provided. The only argument is an object with
+	 * the following properties:
+	 *
+	 *   - source: The filename of the original source.
+	 *   - line: The line number in the original source.
+	 *   - column: The column number in the original source.
+	 *   - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or
+	 *     'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the
+	 *     closest element that is smaller than or greater than the one we are
+	 *     searching for, respectively, if the exact element cannot be found.
+	 *     Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'.
+	 *
+	 * and an object is returned with the following properties:
+	 *
+	 *   - line: The line number in the generated source, or null.
+	 *   - column: The column number in the generated source, or null.
+	 */
+	BasicSourceMapConsumer.prototype.generatedPositionFor = function SourceMapConsumer_generatedPositionFor(aArgs) {
+	  var source = util.getArg(aArgs, 'source');
+	  if (this.sourceRoot != null) {
+	    source = util.relative(this.sourceRoot, source);
+	  }
+	  if (!this._sources.has(source)) {
+	    return {
+	      line: null,
+	      column: null,
+	      lastColumn: null
+	    };
+	  }
+	  source = this._sources.indexOf(source);
+
+	  var needle = {
+	    source: source,
+	    originalLine: util.getArg(aArgs, 'line'),
+	    originalColumn: util.getArg(aArgs, 'column')
+	  };
+
+	  var index = this._findMapping(needle, this._originalMappings, "originalLine", "originalColumn", util.compareByOriginalPositions, util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND));
+
+	  if (index >= 0) {
+	    var mapping = this._originalMappings[index];
+
+	    if (mapping.source === needle.source) {
+	      return {
+	        line: util.getArg(mapping, 'generatedLine', null),
+	        column: util.getArg(mapping, 'generatedColumn', null),
+	        lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)
+	      };
+	    }
+	  }
+
+	  return {
+	    line: null,
+	    column: null,
+	    lastColumn: null
+	  };
+	};
+
+	exports.BasicSourceMapConsumer = BasicSourceMapConsumer;
+
+	/**
+	 * An IndexedSourceMapConsumer instance represents a parsed source map which
+	 * we can query for information. It differs from BasicSourceMapConsumer in
+	 * that it takes "indexed" source maps (i.e. ones with a "sections" field) as
+	 * input.
+	 *
+	 * The only parameter is a raw source map (either as a JSON string, or already
+	 * parsed to an object). According to the spec for indexed source maps, they
+	 * have the following attributes:
+	 *
+	 *   - version: Which version of the source map spec this map is following.
+	 *   - file: Optional. The generated file this source map is associated with.
+	 *   - sections: A list of section definitions.
+	 *
+	 * Each value under the "sections" field has two fields:
+	 *   - offset: The offset into the original specified at which this section
+	 *       begins to apply, defined as an object with a "line" and "column"
+	 *       field.
+	 *   - map: A source map definition. This source map could also be indexed,
+	 *       but doesn't have to be.
+	 *
+	 * Instead of the "map" field, it's also possible to have a "url" field
+	 * specifying a URL to retrieve a source map from, but that's currently
+	 * unsupported.
+	 *
+	 * Here's an example source map, taken from the source map spec[0], but
+	 * modified to omit a section which uses the "url" field.
+	 *
+	 *  {
+	 *    version : 3,
+	 *    file: "app.js",
+	 *    sections: [{
+	 *      offset: {line:100, column:10},
+	 *      map: {
+	 *        version : 3,
+	 *        file: "section.js",
+	 *        sources: ["foo.js", "bar.js"],
+	 *        names: ["src", "maps", "are", "fun"],
+	 *        mappings: "AAAA,E;;ABCDE;"
+	 *      }
+	 *    }],
+	 *  }
+	 *
+	 * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.535es3xeprgt
+	 */
+	function IndexedSourceMapConsumer(aSourceMap) {
+	  var sourceMap = aSourceMap;
+	  if (typeof aSourceMap === 'string') {
+	    sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, ''));
+	  }
+
+	  var version = util.getArg(sourceMap, 'version');
+	  var sections = util.getArg(sourceMap, 'sections');
+
+	  if (version != this._version) {
+	    throw new Error('Unsupported version: ' + version);
+	  }
+
+	  this._sources = new ArraySet();
+	  this._names = new ArraySet();
+
+	  var lastOffset = {
+	    line: -1,
+	    column: 0
+	  };
+	  this._sections = sections.map(function (s) {
+	    if (s.url) {
+	      // The url field will require support for asynchronicity.
+	      // See https://github.com/mozilla/source-map/issues/16
+	      throw new Error('Support for url field in sections not implemented.');
+	    }
+	    var offset = util.getArg(s, 'offset');
+	    var offsetLine = util.getArg(offset, 'line');
+	    var offsetColumn = util.getArg(offset, 'column');
+
+	    if (offsetLine < lastOffset.line || offsetLine === lastOffset.line && offsetColumn < lastOffset.column) {
+	      throw new Error('Section offsets must be ordered and non-overlapping.');
+	    }
+	    lastOffset = offset;
+
+	    return {
+	      generatedOffset: {
+	        // The offset fields are 0-based, but we use 1-based indices when
+	        // encoding/decoding from VLQ.
+	        generatedLine: offsetLine + 1,
+	        generatedColumn: offsetColumn + 1
+	      },
+	      consumer: new SourceMapConsumer(util.getArg(s, 'map'))
+	    };
+	  });
+	}
+
+	IndexedSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype);
+	IndexedSourceMapConsumer.prototype.constructor = SourceMapConsumer;
+
+	/**
+	 * The version of the source mapping spec that we are consuming.
+	 */
+	IndexedSourceMapConsumer.prototype._version = 3;
+
+	/**
+	 * The list of original sources.
+	 */
+	Object.defineProperty(IndexedSourceMapConsumer.prototype, 'sources', {
+	  get: function () {
+	    var sources = [];
+	    for (var i = 0; i < this._sections.length; i++) {
+	      for (var j = 0; j < this._sections[i].consumer.sources.length; j++) {
+	        sources.push(this._sections[i].consumer.sources[j]);
+	      }
+	    }
+	    return sources;
+	  }
+	});
+
+	/**
+	 * Returns the original source, line, and column information for the generated
+	 * source's line and column positions provided. The only argument is an object
+	 * with the following properties:
+	 *
+	 *   - line: The line number in the generated source.
+	 *   - column: The column number in the generated source.
+	 *
+	 * and an object is returned with the following properties:
+	 *
+	 *   - source: The original source file, or null.
+	 *   - line: The line number in the original source, or null.
+	 *   - column: The column number in the original source, or null.
+	 *   - name: The original identifier, or null.
+	 */
+	IndexedSourceMapConsumer.prototype.originalPositionFor = function IndexedSourceMapConsumer_originalPositionFor(aArgs) {
+	  var needle = {
+	    generatedLine: util.getArg(aArgs, 'line'),
+	    generatedColumn: util.getArg(aArgs, 'column')
+	  };
+
+	  // Find the section containing the generated position we're trying to map
+	  // to an original position.
+	  var sectionIndex = binarySearch.search(needle, this._sections, function (needle, section) {
+	    var cmp = needle.generatedLine - section.generatedOffset.generatedLine;
+	    if (cmp) {
+	      return cmp;
+	    }
+
+	    return needle.generatedColumn - section.generatedOffset.generatedColumn;
+	  });
+	  var section = this._sections[sectionIndex];
+
+	  if (!section) {
+	    return {
+	      source: null,
+	      line: null,
+	      column: null,
+	      name: null
+	    };
+	  }
+
+	  return section.consumer.originalPositionFor({
+	    line: needle.generatedLine - (section.generatedOffset.generatedLine - 1),
+	    column: needle.generatedColumn - (section.generatedOffset.generatedLine === needle.generatedLine ? section.generatedOffset.generatedColumn - 1 : 0),
+	    bias: aArgs.bias
+	  });
+	};
+
+	/**
+	 * Return true if we have the source content for every source in the source
+	 * map, false otherwise.
+	 */
+	IndexedSourceMapConsumer.prototype.hasContentsOfAllSources = function IndexedSourceMapConsumer_hasContentsOfAllSources() {
+	  return this._sections.every(function (s) {
+	    return s.consumer.hasContentsOfAllSources();
+	  });
+	};
+
+	/**
+	 * Returns the original source content. The only argument is the url of the
+	 * original source file. Returns null if no original source content is
+	 * available.
+	 */
+	IndexedSourceMapConsumer.prototype.sourceContentFor = function IndexedSourceMapConsumer_sourceContentFor(aSource, nullOnMissing) {
+	  for (var i = 0; i < this._sections.length; i++) {
+	    var section = this._sections[i];
+
+	    var content = section.consumer.sourceContentFor(aSource, true);
+	    if (content) {
+	      return content;
+	    }
+	  }
+	  if (nullOnMissing) {
+	    return null;
+	  } else {
+	    throw new Error('"' + aSource + '" is not in the SourceMap.');
+	  }
+	};
+
+	/**
+	 * Returns the generated line and column information for the original source,
+	 * line, and column positions provided. The only argument is an object with
+	 * the following properties:
+	 *
+	 *   - source: The filename of the original source.
+	 *   - line: The line number in the original source.
+	 *   - column: The column number in the original source.
+	 *
+	 * and an object is returned with the following properties:
+	 *
+	 *   - line: The line number in the generated source, or null.
+	 *   - column: The column number in the generated source, or null.
+	 */
+	IndexedSourceMapConsumer.prototype.generatedPositionFor = function IndexedSourceMapConsumer_generatedPositionFor(aArgs) {
+	  for (var i = 0; i < this._sections.length; i++) {
+	    var section = this._sections[i];
+
+	    // Only consider this section if the requested source is in the list of
+	    // sources of the consumer.
+	    if (section.consumer.sources.indexOf(util.getArg(aArgs, 'source')) === -1) {
+	      continue;
+	    }
+	    var generatedPosition = section.consumer.generatedPositionFor(aArgs);
+	    if (generatedPosition) {
+	      var ret = {
+	        line: generatedPosition.line + (section.generatedOffset.generatedLine - 1),
+	        column: generatedPosition.column + (section.generatedOffset.generatedLine === generatedPosition.line ? section.generatedOffset.generatedColumn - 1 : 0)
+	      };
+	      return ret;
+	    }
+	  }
+
+	  return {
+	    line: null,
+	    column: null
+	  };
+	};
+
+	/**
+	 * Parse the mappings in a string in to a data structure which we can easily
+	 * query (the ordered arrays in the `this.__generatedMappings` and
+	 * `this.__originalMappings` properties).
+	 */
+	IndexedSourceMapConsumer.prototype._parseMappings = function IndexedSourceMapConsumer_parseMappings(aStr, aSourceRoot) {
+	  this.__generatedMappings = [];
+	  this.__originalMappings = [];
+	  for (var i = 0; i < this._sections.length; i++) {
+	    var section = this._sections[i];
+	    var sectionMappings = section.consumer._generatedMappings;
+	    for (var j = 0; j < sectionMappings.length; j++) {
+	      var mapping = sectionMappings[j];
+
+	      var source = section.consumer._sources.at(mapping.source);
+	      if (section.consumer.sourceRoot !== null) {
+	        source = util.join(section.consumer.sourceRoot, source);
+	      }
+	      this._sources.add(source);
+	      source = this._sources.indexOf(source);
+
+	      var name = section.consumer._names.at(mapping.name);
+	      this._names.add(name);
+	      name = this._names.indexOf(name);
+
+	      // The mappings coming from the consumer for the section have
+	      // generated positions relative to the start of the section, so we
+	      // need to offset them to be relative to the start of the concatenated
+	      // generated file.
+	      var adjustedMapping = {
+	        source: source,
+	        generatedLine: mapping.generatedLine + (section.generatedOffset.generatedLine - 1),
+	        generatedColumn: mapping.generatedColumn + (section.generatedOffset.generatedLine === mapping.generatedLine ? section.generatedOffset.generatedColumn - 1 : 0),
+	        originalLine: mapping.originalLine,
+	        originalColumn: mapping.originalColumn,
+	        name: name
+	      };
+
+	      this.__generatedMappings.push(adjustedMapping);
+	      if (typeof adjustedMapping.originalLine === 'number') {
+	        this.__originalMappings.push(adjustedMapping);
+	      }
+	    }
+	  }
+
+	  quickSort(this.__generatedMappings, util.compareByGeneratedPositionsDeflated);
+	  quickSort(this.__originalMappings, util.compareByOriginalPositions);
+	};
+
+	exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer;
+
+/***/ },
+/* 35 */
+/***/ function(module, exports) {
+
+	/* -*- Mode: js; js-indent-level: 2; -*- */
+	/*
+	 * Copyright 2011 Mozilla Foundation and contributors
+	 * Licensed under the New BSD license. See LICENSE or:
+	 * http://opensource.org/licenses/BSD-3-Clause
+	 */
+
+	exports.GREATEST_LOWER_BOUND = 1;
+	exports.LEAST_UPPER_BOUND = 2;
+
+	/**
+	 * Recursive implementation of binary search.
+	 *
+	 * @param aLow Indices here and lower do not contain the needle.
+	 * @param aHigh Indices here and higher do not contain the needle.
+	 * @param aNeedle The element being searched for.
+	 * @param aHaystack The non-empty array being searched.
+	 * @param aCompare Function which takes two elements and returns -1, 0, or 1.
+	 * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or
+	 *     'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the
+	 *     closest element that is smaller than or greater than the one we are
+	 *     searching for, respectively, if the exact element cannot be found.
+	 */
+	function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare, aBias) {
+	  // This function terminates when one of the following is true:
+	  //
+	  //   1. We find the exact element we are looking for.
+	  //
+	  //   2. We did not find the exact element, but we can return the index of
+	  //      the next-closest element.
+	  //
+	  //   3. We did not find the exact element, and there is no next-closest
+	  //      element than the one we are searching for, so we return -1.
+	  var mid = Math.floor((aHigh - aLow) / 2) + aLow;
+	  var cmp = aCompare(aNeedle, aHaystack[mid], true);
+	  if (cmp === 0) {
+	    // Found the element we are looking for.
+	    return mid;
+	  } else if (cmp > 0) {
+	    // Our needle is greater than aHaystack[mid].
+	    if (aHigh - mid > 1) {
+	      // The element is in the upper half.
+	      return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare, aBias);
+	    }
+
+	    // The exact needle element was not found in this haystack. Determine if
+	    // we are in termination case (3) or (2) and return the appropriate thing.
+	    if (aBias == exports.LEAST_UPPER_BOUND) {
+	      return aHigh < aHaystack.length ? aHigh : -1;
+	    } else {
+	      return mid;
+	    }
+	  } else {
+	    // Our needle is less than aHaystack[mid].
+	    if (mid - aLow > 1) {
+	      // The element is in the lower half.
+	      return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare, aBias);
+	    }
+
+	    // we are in termination case (3) or (2) and return the appropriate thing.
+	    if (aBias == exports.LEAST_UPPER_BOUND) {
+	      return mid;
+	    } else {
+	      return aLow < 0 ? -1 : aLow;
+	    }
+	  }
+	}
+
+	/**
+	 * This is an implementation of binary search which will always try and return
+	 * the index of the closest element if there is no exact hit. This is because
+	 * mappings between original and generated line/col pairs are single points,
+	 * and there is an implicit region between each of them, so a miss just means
+	 * that you aren't on the very start of a region.
+	 *
+	 * @param aNeedle The element you are looking for.
+	 * @param aHaystack The array that is being searched.
+	 * @param aCompare A function which takes the needle and an element in the
+	 *     array and returns -1, 0, or 1 depending on whether the needle is less
+	 *     than, equal to, or greater than the element, respectively.
+	 * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or
+	 *     'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the
+	 *     closest element that is smaller than or greater than the one we are
+	 *     searching for, respectively, if the exact element cannot be found.
+	 *     Defaults to 'binarySearch.GREATEST_LOWER_BOUND'.
+	 */
+	exports.search = function search(aNeedle, aHaystack, aCompare, aBias) {
+	  if (aHaystack.length === 0) {
+	    return -1;
+	  }
+
+	  var index = recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare, aBias || exports.GREATEST_LOWER_BOUND);
+	  if (index < 0) {
+	    return -1;
+	  }
+
+	  // We have found either the exact element, or the next-closest element than
+	  // the one we are searching for. However, there may be more than one such
+	  // element. Make sure we always return the smallest of these.
+	  while (index - 1 >= 0) {
+	    if (aCompare(aHaystack[index], aHaystack[index - 1], true) !== 0) {
+	      break;
+	    }
+	    --index;
+	  }
+
+	  return index;
+	};
+
+/***/ },
+/* 36 */
+/***/ function(module, exports) {
+
+	/* -*- Mode: js; js-indent-level: 2; -*- */
+	/*
+	 * Copyright 2011 Mozilla Foundation and contributors
+	 * Licensed under the New BSD license. See LICENSE or:
+	 * http://opensource.org/licenses/BSD-3-Clause
+	 */
+
+	// It turns out that some (most?) JavaScript engines don't self-host
+	// `Array.prototype.sort`. This makes sense because C++ will likely remain
+	// faster than JS when doing raw CPU-intensive sorting. However, when using a
+	// custom comparator function, calling back and forth between the VM's C++ and
+	// JIT'd JS is rather slow *and* loses JIT type information, resulting in
+	// worse generated code for the comparator function than would be optimal. In
+	// fact, when sorting with a comparator, these costs outweigh the benefits of
+	// sorting in C++. By using our own JS-implemented Quick Sort (below), we get
+	// a ~3500ms mean speed-up in `bench/bench.html`.
+
+	/**
+	 * Swap the elements indexed by `x` and `y` in the array `ary`.
+	 *
+	 * @param {Array} ary
+	 *        The array.
+	 * @param {Number} x
+	 *        The index of the first item.
+	 * @param {Number} y
+	 *        The index of the second item.
+	 */
+	function swap(ary, x, y) {
+	  var temp = ary[x];
+	  ary[x] = ary[y];
+	  ary[y] = temp;
+	}
+
+	/**
+	 * Returns a random integer within the range `low .. high` inclusive.
+	 *
+	 * @param {Number} low
+	 *        The lower bound on the range.
+	 * @param {Number} high
+	 *        The upper bound on the range.
+	 */
+	function randomIntInRange(low, high) {
+	  return Math.round(low + Math.random() * (high - low));
+	}
+
+	/**
+	 * The Quick Sort algorithm.
+	 *
+	 * @param {Array} ary
+	 *        An array to sort.
+	 * @param {function} comparator
+	 *        Function to use to compare two items.
+	 * @param {Number} p
+	 *        Start index of the array
+	 * @param {Number} r
+	 *        End index of the array
+	 */
+	function doQuickSort(ary, comparator, p, r) {
+	  // If our lower bound is less than our upper bound, we (1) partition the
+	  // array into two pieces and (2) recurse on each half. If it is not, this is
+	  // the empty array and our base case.
+
+	  if (p < r) {
+	    // (1) Partitioning.
+	    //
+	    // The partitioning chooses a pivot between `p` and `r` and moves all
+	    // elements that are less than or equal to the pivot to the before it, and
+	    // all the elements that are greater than it after it. The effect is that
+	    // once partition is done, the pivot is in the exact place it will be when
+	    // the array is put in sorted order, and it will not need to be moved
+	    // again. This runs in O(n) time.
+
+	    // Always choose a random pivot so that an input array which is reverse
+	    // sorted does not cause O(n^2) running time.
+	    var pivotIndex = randomIntInRange(p, r);
+	    var i = p - 1;
+
+	    swap(ary, pivotIndex, r);
+	    var pivot = ary[r];
+
+	    // Immediately after `j` is incremented in this loop, the following hold
+	    // true:
+	    //
+	    //   * Every element in `ary[p .. i]` is less than or equal to the pivot.
+	    //
+	    //   * Every element in `ary[i+1 .. j-1]` is greater than the pivot.
+	    for (var j = p; j < r; j++) {
+	      if (comparator(ary[j], pivot) <= 0) {
+	        i += 1;
+	        swap(ary, i, j);
+	      }
+	    }
+
+	    swap(ary, i + 1, j);
+	    var q = i + 1;
+
+	    // (2) Recurse on each half.
+
+	    doQuickSort(ary, comparator, p, q - 1);
+	    doQuickSort(ary, comparator, q + 1, r);
+	  }
+	}
+
+	/**
+	 * Sort the given array in-place with the given comparator function.
+	 *
+	 * @param {Array} ary
+	 *        An array to sort.
+	 * @param {function} comparator
+	 *        Function to use to compare two items.
+	 */
+	exports.quickSort = function (ary, comparator) {
+	  doQuickSort(ary, comparator, 0, ary.length - 1);
+	};
+
+/***/ },
+/* 37 */
+/***/ function(module, exports, __webpack_require__) {
+
+	/* -*- Mode: js; js-indent-level: 2; -*- */
+	/*
+	 * Copyright 2011 Mozilla Foundation and contributors
+	 * Licensed under the New BSD license. See LICENSE or:
+	 * http://opensource.org/licenses/BSD-3-Clause
+	 */
+
+	var SourceMapGenerator = __webpack_require__(28).SourceMapGenerator;
+	var util = __webpack_require__(31);
+
+	// Matches a Windows-style `\r\n` newline or a `\n` newline used by all other
+	// operating systems these days (capturing the result).
+	var REGEX_NEWLINE = /(\r?\n)/;
+
+	// Newline character code for charCodeAt() comparisons
+	var NEWLINE_CODE = 10;
+
+	// Private symbol for identifying `SourceNode`s when multiple versions of
+	// the source-map library are loaded. This MUST NOT CHANGE across
+	// versions!
+	var isSourceNode = "$$$isSourceNode$$$";
+
+	/**
+	 * SourceNodes provide a way to abstract over interpolating/concatenating
+	 * snippets of generated JavaScript source code while maintaining the line and
+	 * column information associated with the original source code.
+	 *
+	 * @param aLine The original line number.
+	 * @param aColumn The original column number.
+	 * @param aSource The original source's filename.
+	 * @param aChunks Optional. An array of strings which are snippets of
+	 *        generated JS, or other SourceNodes.
+	 * @param aName The original identifier.
+	 */
+	function SourceNode(aLine, aColumn, aSource, aChunks, aName) {
+	  this.children = [];
+	  this.sourceContents = {};
+	  this.line = aLine == null ? null : aLine;
+	  this.column = aColumn == null ? null : aColumn;
+	  this.source = aSource == null ? null : aSource;
+	  this.name = aName == null ? null : aName;
+	  this[isSourceNode] = true;
+	  if (aChunks != null) this.add(aChunks);
+	}
+
+	/**
+	 * Creates a SourceNode from generated code and a SourceMapConsumer.
+	 *
+	 * @param aGeneratedCode The generated code
+	 * @param aSourceMapConsumer The SourceMap for the generated code
+	 * @param aRelativePath Optional. The path that relative sources in the
+	 *        SourceMapConsumer should be relative to.
+	 */
+	SourceNode.fromStringWithSourceMap = function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) {
+	  // The SourceNode we want to fill with the generated code
+	  // and the SourceMap
+	  var node = new SourceNode();
+
+	  // All even indices of this array are one line of the generated code,
+	  // while all odd indices are the newlines between two adjacent lines
+	  // (since `REGEX_NEWLINE` captures its match).
+	  // Processed fragments are accessed by calling `shiftNextLine`.
+	  var remainingLines = aGeneratedCode.split(REGEX_NEWLINE);
+	  var remainingLinesIndex = 0;
+	  var shiftNextLine = function () {
+	    var lineContents = getNextLine();
+	    // The last line of a file might not have a newline.
+	    var newLine = getNextLine() || "";
+	    return lineContents + newLine;
+
+	    function getNextLine() {
+	      return remainingLinesIndex < remainingLines.length ? remainingLines[remainingLinesIndex++] : undefined;
+	    }
+	  };
+
+	  // We need to remember the position of "remainingLines"
+	  var lastGeneratedLine = 1,
+	      lastGeneratedColumn = 0;
+
+	  // The generate SourceNodes we need a code range.
+	  // To extract it current and last mapping is used.
+	  // Here we store the last mapping.
+	  var lastMapping = null;
+
+	  aSourceMapConsumer.eachMapping(function (mapping) {
+	    if (lastMapping !== null) {
+	      // We add the code from "lastMapping" to "mapping":
+	      // First check if there is a new line in between.
+	      if (lastGeneratedLine < mapping.generatedLine) {
+	        // Associate first line with "lastMapping"
+	        addMappingWithCode(lastMapping, shiftNextLine());
+	        lastGeneratedLine++;
+	        lastGeneratedColumn = 0;
+	        // The remaining code is added without mapping
+	      } else {
+	        // There is no new line in between.
+	        // Associate the code between "lastGeneratedColumn" and
+	        // "mapping.generatedColumn" with "lastMapping"
+	        var nextLine = remainingLines[remainingLinesIndex];
+	        var code = nextLine.substr(0, mapping.generatedColumn - lastGeneratedColumn);
+	        remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn - lastGeneratedColumn);
+	        lastGeneratedColumn = mapping.generatedColumn;
+	        addMappingWithCode(lastMapping, code);
+	        // No more remaining code, continue
+	        lastMapping = mapping;
+	        return;
+	      }
+	    }
+	    // We add the generated code until the first mapping
+	    // to the SourceNode without any mapping.
+	    // Each line is added as separate string.
+	    while (lastGeneratedLine < mapping.generatedLine) {
+	      node.add(shiftNextLine());
+	      lastGeneratedLine++;
+	    }
+	    if (lastGeneratedColumn < mapping.generatedColumn) {
+	      var nextLine = remainingLines[remainingLinesIndex];
+	      node.add(nextLine.substr(0, mapping.generatedColumn));
+	      remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn);
+	      lastGeneratedColumn = mapping.generatedColumn;
+	    }
+	    lastMapping = mapping;
+	  }, this);
+	  // We have processed all mappings.
+	  if (remainingLinesIndex < remainingLines.length) {
+	    if (lastMapping) {
+	      // Associate the remaining code in the current line with "lastMapping"
+	      addMappingWithCode(lastMapping, shiftNextLine());
+	    }
+	    // and add the remaining lines without any mapping
+	    node.add(remainingLines.splice(remainingLinesIndex).join(""));
+	  }
+
+	  // Copy sourcesContent into SourceNode
+	  aSourceMapConsumer.sources.forEach(function (sourceFile) {
+	    var content = aSourceMapConsumer.sourceContentFor(sourceFile);
+	    if (content != null) {
+	      if (aRelativePath != null) {
+	        sourceFile = util.join(aRelativePath, sourceFile);
+	      }
+	      node.setSourceContent(sourceFile, content);
+	    }
+	  });
+
+	  return node;
+
+	  function addMappingWithCode(mapping, code) {
+	    if (mapping === null || mapping.source === undefined) {
+	      node.add(code);
+	    } else {
+	      var source = aRelativePath ? util.join(aRelativePath, mapping.source) : mapping.source;
+	      node.add(new SourceNode(mapping.originalLine, mapping.originalColumn, source, code, mapping.name));
+	    }
+	  }
+	};
+
+	/**
+	 * Add a chunk of generated JS to this source node.
+	 *
+	 * @param aChunk A string snippet of generated JS code, another instance of
+	 *        SourceNode, or an array where each member is one of those things.
+	 */
+	SourceNode.prototype.add = function SourceNode_add(aChunk) {
+	  if (Array.isArray(aChunk)) {
+	    aChunk.forEach(function (chunk) {
+	      this.add(chunk);
+	    }, this);
+	  } else if (aChunk[isSourceNode] || typeof aChunk === "string") {
+	    if (aChunk) {
+	      this.children.push(aChunk);
+	    }
+	  } else {
+	    throw new TypeError("Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk);
+	  }
+	  return this;
+	};
+
+	/**
+	 * Add a chunk of generated JS to the beginning of this source node.
+	 *
+	 * @param aChunk A string snippet of generated JS code, another instance of
+	 *        SourceNode, or an array where each member is one of those things.
+	 */
+	SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) {
+	  if (Array.isArray(aChunk)) {
+	    for (var i = aChunk.length - 1; i >= 0; i--) {
+	      this.prepend(aChunk[i]);
+	    }
+	  } else if (aChunk[isSourceNode] || typeof aChunk === "string") {
+	    this.children.unshift(aChunk);
+	  } else {
+	    throw new TypeError("Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk);
+	  }
+	  return this;
+	};
+
+	/**
+	 * Walk over the tree of JS snippets in this node and its children. The
+	 * walking function is called once for each snippet of JS and is passed that
+	 * snippet and the its original associated source's line/column location.
+	 *
+	 * @param aFn The traversal function.
+	 */
+	SourceNode.prototype.walk = function SourceNode_walk(aFn) {
+	  var chunk;
+	  for (var i = 0, len = this.children.length; i < len; i++) {
+	    chunk = this.children[i];
+	    if (chunk[isSourceNode]) {
+	      chunk.walk(aFn);
+	    } else {
+	      if (chunk !== '') {
+	        aFn(chunk, { source: this.source,
+	          line: this.line,
+	          column: this.column,
+	          name: this.name });
+	      }
+	    }
+	  }
+	};
+
+	/**
+	 * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between
+	 * each of `this.children`.
+	 *
+	 * @param aSep The separator.
+	 */
+	SourceNode.prototype.join = function SourceNode_join(aSep) {
+	  var newChildren;
+	  var i;
+	  var len = this.children.length;
+	  if (len > 0) {
+	    newChildren = [];
+	    for (i = 0; i < len - 1; i++) {
+	      newChildren.push(this.children[i]);
+	      newChildren.push(aSep);
+	    }
+	    newChildren.push(this.children[i]);
+	    this.children = newChildren;
+	  }
+	  return this;
+	};
+
+	/**
+	 * Call String.prototype.replace on the very right-most source snippet. Useful
+	 * for trimming whitespace from the end of a source node, etc.
+	 *
+	 * @param aPattern The pattern to replace.
+	 * @param aReplacement The thing to replace the pattern with.
+	 */
+	SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) {
+	  var lastChild = this.children[this.children.length - 1];
+	  if (lastChild[isSourceNode]) {
+	    lastChild.replaceRight(aPattern, aReplacement);
+	  } else if (typeof lastChild === 'string') {
+	    this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement);
+	  } else {
+	    this.children.push(''.replace(aPattern, aReplacement));
+	  }
+	  return this;
+	};
+
+	/**
+	 * Set the source content for a source file. This will be added to the SourceMapGenerator
+	 * in the sourcesContent field.
+	 *
+	 * @param aSourceFile The filename of the source file
+	 * @param aSourceContent The content of the source file
+	 */
+	SourceNode.prototype.setSourceContent = function SourceNode_setSourceContent(aSourceFile, aSourceContent) {
+	  this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent;
+	};
+
+	/**
+	 * Walk over the tree of SourceNodes. The walking function is called for each
+	 * source file content and is passed the filename and source content.
+	 *
+	 * @param aFn The traversal function.
+	 */
+	SourceNode.prototype.walkSourceContents = function SourceNode_walkSourceContents(aFn) {
+	  for (var i = 0, len = this.children.length; i < len; i++) {
+	    if (this.children[i][isSourceNode]) {
+	      this.children[i].walkSourceContents(aFn);
+	    }
+	  }
+
+	  var sources = Object.keys(this.sourceContents);
+	  for (var i = 0, len = sources.length; i < len; i++) {
+	    aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]);
+	  }
+	};
+
+	/**
+	 * Return the string representation of this source node. Walks over the tree
+	 * and concatenates all the various snippets together to one string.
+	 */
+	SourceNode.prototype.toString = function SourceNode_toString() {
+	  var str = "";
+	  this.walk(function (chunk) {
+	    str += chunk;
+	  });
+	  return str;
+	};
+
+	/**
+	 * Returns the string representation of this source node along with a source
+	 * map.
+	 */
+	SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) {
+	  var generated = {
+	    code: "",
+	    line: 1,
+	    column: 0
+	  };
+	  var map = new SourceMapGenerator(aArgs);
+	  var sourceMappingActive = false;
+	  var lastOriginalSource = null;
+	  var lastOriginalLine = null;
+	  var lastOriginalColumn = null;
+	  var lastOriginalName = null;
+	  this.walk(function (chunk, original) {
+	    generated.code += chunk;
+	    if (original.source !== null && original.line !== null && original.column !== null) {
+	      if (lastOriginalSource !== original.source || lastOriginalLine !== original.line || lastOriginalColumn !== original.column || lastOriginalName !== original.name) {
+	        map.addMapping({
+	          source: original.source,
+	          original: {
+	            line: original.line,
+	            column: original.column
+	          },
+	          generated: {
+	            line: generated.line,
+	            column: generated.column
+	          },
+	          name: original.name
+	        });
+	      }
+	      lastOriginalSource = original.source;
+	      lastOriginalLine = original.line;
+	      lastOriginalColumn = original.column;
+	      lastOriginalName = original.name;
+	      sourceMappingActive = true;
+	    } else if (sourceMappingActive) {
+	      map.addMapping({
+	        generated: {
+	          line: generated.line,
+	          column: generated.column
+	        }
+	      });
+	      lastOriginalSource = null;
+	      sourceMappingActive = false;
+	    }
+	    for (var idx = 0, length = chunk.length; idx < length; idx++) {
+	      if (chunk.charCodeAt(idx) === NEWLINE_CODE) {
+	        generated.line++;
+	        generated.column = 0;
+	        // Mappings end at eol
+	        if (idx + 1 === length) {
+	          lastOriginalSource = null;
+	          sourceMappingActive = false;
+	        } else if (sourceMappingActive) {
+	          map.addMapping({
+	            source: original.source,
+	            original: {
+	              line: original.line,
+	              column: original.column
+	            },
+	            generated: {
+	              line: generated.line,
+	              column: generated.column
+	            },
+	            name: original.name
+	          });
+	        }
+	      } else {
+	        generated.column++;
+	      }
+	    }
+	  });
+	  this.walkSourceContents(function (sourceFile, sourceContent) {
+	    map.setSourceContent(sourceFile, sourceContent);
+	  });
+
+	  return { code: generated.code, map: map };
+	};
+
+	exports.SourceNode = SourceNode;
+
 /***/ }
 /******/ ])
 });
 ;
\ No newline at end of file
--- a/dom/browser-element/mochitest/browserElement_PromptCheck.js
+++ b/dom/browser-element/mochitest/browserElement_PromptCheck.js
@@ -8,16 +8,17 @@
 // At the moment, we treat alertCheck/promptCheck/confirmCheck just like a
 // normal alert.  But it's different to nsIPrompt!
 
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
+browserElementTestHelpers.allowTopLevelDataURINavigation();
 
 function runTest()
 {
   var iframe = document.createElement('iframe');
   iframe.setAttribute('mozbrowser', 'true');
   document.body.appendChild(iframe);
 
   var numPrompts = 0;
--- a/dom/browser-element/mochitest/browserElement_PromptConfirm.js
+++ b/dom/browser-element/mochitest/browserElement_PromptConfirm.js
@@ -6,16 +6,17 @@
 //
 // We use alert() to communicate the return values of prompt/confirm back to
 // ourselves.
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
+browserElementTestHelpers.allowTopLevelDataURINavigation();
 
 function runTest() {
   var iframe = document.createElement('iframe');
   iframe.setAttribute('mozbrowser', 'true');
   document.body.appendChild(iframe);
 
   var prompts = [
     {msg: '1', type: 'alert', rv: 42, expected: 'undefined'},
--- a/dom/browser-element/mochitest/browserElement_RemoveBrowserElement.js
+++ b/dom/browser-element/mochitest/browserElement_RemoveBrowserElement.js
@@ -4,16 +4,17 @@
 // Bug 787517: Remove iframe in the handler of showmodalprompt. This shouldn't
 // cause an exception to be thrown.
 
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
+browserElementTestHelpers.allowTopLevelDataURINavigation();
 
 function runTest() {
   var iframe = document.createElement('iframe');
   iframe.setAttribute('mozbrowser', 'true');
   document.body.appendChild(iframe);
 
   iframe.addEventListener("mozbrowsershowmodalprompt", function(e) {
     document.body.removeChild(iframe);
--- a/dom/browser-element/mochitest/browserElement_ScrollEvent.js
+++ b/dom/browser-element/mochitest/browserElement_ScrollEvent.js
@@ -2,16 +2,17 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test that scroll event bubbles up.
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
+browserElementTestHelpers.allowTopLevelDataURINavigation();
 
 function runTest() {
   var iframe = document.createElement('iframe');
   iframe.setAttribute('mozbrowser', 'true');
   document.body.appendChild(iframe);
 
   iframe.addEventListener("mozbrowserscroll", function(e) {
     ok(true, "got mozbrowserscroll event.");
--- a/dom/browser-element/mochitest/browserElement_Titlechange.js
+++ b/dom/browser-element/mochitest/browserElement_Titlechange.js
@@ -2,16 +2,17 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test that the onmozbrowsertitlechange event works.
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.addPermission();
+browserElementTestHelpers.allowTopLevelDataURINavigation();
 
 function runTest() {
   var iframe1 = document.createElement('iframe');
   iframe1.setAttribute('mozbrowser', 'true');
   document.body.appendChild(iframe1);
 
   // iframe2 is a red herring; we modify its title but don't listen for
   // titlechanges; we want to make sure that its titlechange events aren't
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -1135,17 +1135,16 @@ TabParent::SendRealMouseEvent(WidgetMous
         widget->SetCursor(mCursor);
       }
     } else if (eMouseExitFromWidget == aEvent.mMessage) {
       mTabSetsCursor = false;
     }
   }
   if (!mIsReadyToHandleInputEvents) {
     if (eMouseEnterIntoWidget == aEvent.mMessage) {
-      MOZ_ASSERT(!mIsMouseEnterIntoWidgetEventSuppressed);
       mIsMouseEnterIntoWidgetEventSuppressed = true;
     } else if (eMouseExitFromWidget == aEvent.mMessage) {
       mIsMouseEnterIntoWidgetEventSuppressed = false;
     }
     return;
   }
 
   ScrollableLayerGuid guid;
--- a/dom/webauthn/tests/browser/browser_webauthn_telemetry.js
+++ b/dom/webauthn/tests/browser/browser_webauthn_telemetry.js
@@ -77,33 +77,11 @@ add_task(async function test_loopback() 
     is(webauthn_used["U2FSignFinish"], 1, "webauthn_used U2FSignFinish scalar should be 1");
     is(webauthn_used["U2FSignAbort"], undefined, "webauthn_used U2FSignAbort scalar must be unset");
     is(webauthn_used["U2FRegisterAbort"], undefined, "webauthn_used U2FRegisterAbort scalar must be unset");
 
     validateHistogramEntryCount("WEBAUTHN_CREATE_CREDENTIAL_MS", 1);
     validateHistogramEntryCount("WEBAUTHN_GET_ASSERTION_MS", 1);
   }
 
-  /*{
-    cleanupTelemetry();
-    // Same as test_successful_loopback, but we will swap to using a (non-existent)
-    // usb token. This will cause U2FRegisterAbort to fire, but will not execute the
-    // Sign function, and no histogram entries will log.
-    Services.prefs.setBoolPref("security.webauth.webauthn", true);
-    Services.prefs.setBoolPref("security.webauth.webauthn_enable_softtoken", false);
-    Services.prefs.setBoolPref("security.webauth.webauthn_enable_usbtoken", true);
-
-    await executeTestPage(testPage);
-
-    let webauthn_used = getTelemetryForScalar("security.webauthn_used");
-    ok(webauthn_used, "Scalar keys are set: " + Object.keys(webauthn_used).join(", "));
-    is(webauthn_used["U2FRegisterFinish"], undefined, "webauthn_used U2FRegisterFinish must be unset");
-    is(webauthn_used["U2FSignFinish"], undefined, "webauthn_used U2FSignFinish scalar must be unset");
-    is(webauthn_used["U2FRegisterAbort"], 1, "webauthn_used U2FRegisterAbort scalar should be a 1");
-    is(webauthn_used["U2FSignAbort"], undefined, "webauthn_used U2FSignAbort scalar must be unset");
-
-    validateHistogramEntryCount("WEBAUTHN_CREATE_CREDENTIAL_MS", 0);
-    validateHistogramEntryCount("WEBAUTHN_GET_ASSERTION_MS", 0);
-  }*/
-
   // There aren't tests for register succeeding and sign failing, as I don't see an easy way to prompt
   // the soft token to fail that way _and_ trigger the Abort telemetry.
 });
--- a/dom/webauthn/u2f-hid-rs/src/lib.rs
+++ b/dom/webauthn/u2f-hid-rs/src/lib.rs
@@ -18,18 +18,18 @@ extern crate core_foundation_sys;
 #[cfg(any(target_os = "macos"))]
 #[path = "macos/mod.rs"]
 pub mod platform;
 
 #[cfg(any(target_os = "windows"))]
 #[path = "windows/mod.rs"]
 pub mod platform;
 
-#[cfg(any(target_os = "android"))]
-#[path = "android/mod.rs"]
+#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
+#[path = "stub/mod.rs"]
 pub mod platform;
 
 #[macro_use]
 extern crate log;
 extern crate rand;
 extern crate libc;
 extern crate boxfnonce;
 
rename from dom/webauthn/u2f-hid-rs/src/android/mod.rs
rename to dom/webauthn/u2f-hid-rs/src/stub/mod.rs
--- a/gfx/layers/wr/WebRenderLayerManager.cpp
+++ b/gfx/layers/wr/WebRenderLayerManager.cpp
@@ -371,17 +371,16 @@ WebRenderLayerManager::CreateWebRenderCo
 }
 
 void
 WebRenderLayerManager::EndTransactionWithoutLayer(nsDisplayList* aDisplayList,
                                                   nsDisplayListBuilder* aDisplayListBuilder)
 {
   MOZ_ASSERT(aDisplayList && aDisplayListBuilder);
   mEndTransactionWithoutLayers = true;
-  DiscardImages();
   WrBridge()->RemoveExpiredFontKeys();
   EndTransactionInternal(nullptr,
                          nullptr,
                          EndTransactionFlags::END_DEFAULT,
                          aDisplayList,
                          aDisplayListBuilder);
 }
 
@@ -681,17 +680,16 @@ WebRenderLayerManager::PushItemAsImage(n
 }
 
 void
 WebRenderLayerManager::EndTransaction(DrawPaintedLayerCallback aCallback,
                                       void* aCallbackData,
                                       EndTransactionFlags aFlags)
 {
   mEndTransactionWithoutLayers = false;
-  DiscardImages();
   WrBridge()->RemoveExpiredFontKeys();
   EndTransactionInternal(aCallback, aCallbackData, aFlags);
 }
 
 bool
 WebRenderLayerManager::EndTransactionInternal(DrawPaintedLayerCallback aCallback,
                                               void* aCallbackData,
                                               EndTransactionFlags aFlags,
@@ -812,16 +810,21 @@ WebRenderLayerManager::EndTransactionInt
     }
     mScrollData.SetPaintSequenceNumber(mPaintSequenceNumber);
   }
 
   bool sync = mTarget != nullptr;
   mLatestTransactionId = mTransactionIdAllocator->GetTransactionId(/*aThrottle*/ true);
   TimeStamp transactionStart = mTransactionIdAllocator->GetTransactionStart();
 
+  for (const auto& key : mImageKeysToDelete) {
+    resourceUpdates.DeleteImage(key);
+  }
+  mImageKeysToDelete.Clear();
+
   // Skip the synchronization for buffer since we also skip the painting during
   // device-reset status.
   if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) {
     if (WrBridge()->GetSyncObject() &&
         WrBridge()->GetSyncObject()->IsSyncObjectValid()) {
       WrBridge()->GetSyncObject()->Synchronize();
     }
   }
new file mode 100644
--- /dev/null
+++ b/intl/icu-patches/bug-1387937.diff
@@ -0,0 +1,23 @@
+Bug 1387937 - Import changeset 40324.
+
+diff --git a/intl/icu/source/i18n/zonemeta.cpp b/intl/icu/source/i18n/zonemeta.cpp
+--- a/intl/icu/source/i18n/zonemeta.cpp
++++ b/intl/icu/source/i18n/zonemeta.cpp
+@@ -685,17 +685,16 @@ ZoneMeta::createMetazoneMappings(const U
+                 entry->mzid = mz_name;
+                 entry->from = from;
+                 entry->to = to;
+ 
+                 if (mzMappings == NULL) {
+                     mzMappings = new UVector(deleteOlsonToMetaMappingEntry, NULL, status);
+                     if (U_FAILURE(status)) {
+                         delete mzMappings;
+-                        deleteOlsonToMetaMappingEntry(entry);
+                         uprv_free(entry);
+                         break;
+                     }
+                 }
+ 
+                 mzMappings->addElement(entry, status);
+                 if (U_FAILURE(status)) {
+                     break;
--- a/intl/icu/source/i18n/zonemeta.cpp
+++ b/intl/icu/source/i18n/zonemeta.cpp
@@ -685,17 +685,16 @@ ZoneMeta::createMetazoneMappings(const U
                 entry->mzid = mz_name;
                 entry->from = from;
                 entry->to = to;
 
                 if (mzMappings == NULL) {
                     mzMappings = new UVector(deleteOlsonToMetaMappingEntry, NULL, status);
                     if (U_FAILURE(status)) {
                         delete mzMappings;
-                        deleteOlsonToMetaMappingEntry(entry);
                         uprv_free(entry);
                         break;
                     }
                 }
 
                 mzMappings->addElement(entry, status);
                 if (U_FAILURE(status)) {
                     break;
--- a/intl/update-icu.sh
+++ b/intl/update-icu.sh
@@ -68,16 +68,17 @@ svn info $1 | grep -v '^Revision: [[:dig
 for patch in \
  bug-915735 \
  suppress-warnings.diff \
  bug-1172609-timezone-recreateDefault.diff \
  bug-1198952-workaround-make-3.82-bug.diff \
  u_setMemoryFunctions-callconvention-anachronism-msvc.diff \
  bug-1373763-convertToPosix-stack-value-out-of-scope.diff \
  bug-1380083 \
+ bug-1387937.diff \
 ; do
   echo "Applying local patch $patch"
   patch -d ${icu_dir}/../../ -p1 --no-backup-if-mismatch < ${icu_dir}/../icu-patches/$patch
 done
 
 topsrcdir=`dirname $0`/../
 python ${topsrcdir}/js/src/tests/ecma_6/String/make-normalize-generateddata-input.py $topsrcdir
 
--- a/ipc/chromium/src/chrome/common/ipc_message.cc
+++ b/ipc/chromium/src/chrome/common/ipc_message.cc
@@ -33,79 +33,72 @@ namespace IPC {
 
 Message::~Message() {
   MOZ_COUNT_DTOR(IPC::Message);
 }
 
 Message::Message()
     : Pickle(MSG_HEADER_SZ) {
   MOZ_COUNT_CTOR(IPC::Message);
-  header()->routing = header()->type = header()->flags = 0;
+  header()->routing = header()->type = 0;
 #if defined(OS_POSIX)
   header()->num_fds = 0;
 #endif
 #ifdef MOZ_TASK_TRACER
   if (UseTaskTracerHeader()) {
-    header()->flags |= TASKTRACER_BIT;
+    header()->flags.SetTaskTracer();
     HeaderTaskTracer* _header = static_cast<HeaderTaskTracer*>(header());
     GetCurTraceInfo(&_header->source_event_id,
                     &_header->parent_task_id,
                     &_header->source_event_type);
   }
 #endif
   InitLoggingVariables();
 }
 
 Message::Message(int32_t routing_id,
                  msgid_t type,
                  uint32_t segment_capacity,
-                 NestedLevel nestedLevel,
-                 PriorityValue priority,
-                 MessageCompression compression,
+                 HeaderFlags flags,
                  const char* const aName,
                  bool recordWriteLatency)
     : Pickle(MSG_HEADER_SZ, segment_capacity) {
   MOZ_COUNT_CTOR(IPC::Message);
   header()->routing = routing_id;
   header()->type = type;
-  header()->flags = nestedLevel;
-  set_priority(priority);
-  if (compression == COMPRESSION_ENABLED)
-    header()->flags |= COMPRESS_BIT;
-  else if (compression == COMPRESSION_ALL)
-    header()->flags |= COMPRESSALL_BIT;
+  header()->flags = flags;
 #if defined(OS_POSIX)
   header()->num_fds = 0;
 #endif
   header()->interrupt_remote_stack_depth_guess = static_cast<uint32_t>(-1);
   header()->interrupt_local_stack_depth = static_cast<uint32_t>(-1);
   header()->seqno = 0;
 #if defined(OS_MACOSX)
   header()->cookie = 0;
 #endif
 #ifdef MOZ_TASK_TRACER
   if (UseTaskTracerHeader()) {
-    header()->flags |= TASKTRACER_BIT;
+    header()->flags.SetTaskTracer();
     HeaderTaskTracer* _header = static_cast<HeaderTaskTracer*>(header());
     GetCurTraceInfo(&_header->source_event_id,
                     &_header->parent_task_id,
                     &_header->source_event_type);
   }
 #endif
   if (recordWriteLatency) {
     create_time_ = mozilla::TimeStamp::Now();
   }
   InitLoggingVariables(aName);
 }
 
 #ifndef MOZ_TASK_TRACER
 #define MSG_HEADER_SZ_DATA sizeof(Header)
 #else
 #define MSG_HEADER_SZ_DATA                                            \
-  (reinterpret_cast<const Header*>(data)->flags & TASKTRACER_BIT ?  \
+  (reinterpret_cast<const Header*>(data)->flags.IsTaskTracer() ? \
    sizeof(HeaderTaskTracer) : sizeof(Header))
 #endif
 
 Message::Message(const char* data, int data_len)
   : Pickle(MSG_HEADER_SZ_DATA, data, data_len)
 {
   MOZ_COUNT_CTOR(IPC::Message);
   InitLoggingVariables();
@@ -114,16 +107,47 @@ Message::Message(const char* data, int d
 Message::Message(Message&& other) : Pickle(mozilla::Move(other)) {
   MOZ_COUNT_CTOR(IPC::Message);
   InitLoggingVariables(other.name_);
 #if defined(OS_POSIX)
   file_descriptor_set_ = other.file_descriptor_set_.forget();
 #endif
 }
 
+/*static*/ Message*
+Message::IPDLMessage(int32_t routing_id,
+                     msgid_t type,
+                     HeaderFlags flags,
+                     const char* const name)
+{
+  return new Message(routing_id, type, 0, flags, name, true);
+}
+
+/*static*/ Message*
+Message::ForSyncDispatchError(NestedLevel level)
+{
+  auto* m = new Message(0, 0, 0, HeaderFlags(level));
+  auto& flags = m->header()->flags;
+  flags.SetSync();
+  flags.SetReply();
+  flags.SetReplyError();
+  return m;
+}
+
+/*static*/ Message*
+Message::ForInterruptDispatchError()
+{
+  auto* m = new Message();
+  auto& flags = m->header()->flags;
+  flags.SetInterrupt();
+  flags.SetReply();
+  flags.SetReplyError();
+  return m;
+}
+
 void Message::InitLoggingVariables(const char* const aName) {
   name_ = aName;
 }
 
 Message& Message::operator=(Message&& other) {
   *static_cast<Pickle*>(this) = mozilla::Move(other);
   InitLoggingVariables(other.name_);
 #if defined(OS_POSIX)
@@ -176,17 +200,17 @@ uint32_t Message::num_fds() const {
 
 #ifdef MOZ_TASK_TRACER
 void *MessageTask() {
   return reinterpret_cast<void*>(&MessageTask);
 }
 
 void
 Message::TaskTracerDispatch() {
-  if (header()->flags & TASKTRACER_BIT) {
+  if (header()->flags.IsTaskTracer()) {
     HeaderTaskTracer* _header = static_cast<HeaderTaskTracer*>(header());
     _header->task_id = GenNewUniqueTaskId();
     uintptr_t* vtab = reinterpret_cast<uintptr_t*>(&MessageTask);
     LogVirtualTablePtr(_header->task_id,
                        _header->source_event_id,
                        vtab);
     LogDispatch(_header->task_id,
                 _header->parent_task_id,
@@ -194,17 +218,17 @@ Message::TaskTracerDispatch() {
                 _header->source_event_type);
   }
 }
 
 Message::AutoTaskTracerRun::AutoTaskTracerRun(Message& aMsg)
   : mMsg(aMsg)
   , mTaskId(0)
   , mSourceEventId(0) {
-  if (mMsg.header()->flags & TASKTRACER_BIT) {
+  if (mMsg.header()->flags.IsTaskTracer()) {
     const HeaderTaskTracer* _header =
       static_cast<HeaderTaskTracer*>(mMsg.header());
     LogBegin(_header->task_id,
              _header->source_event_id);
     SetCurTraceInfo(_header->source_event_id,
                     _header->task_id,
                     _header->source_event_type);
     mTaskId = _header->task_id;
--- a/ipc/chromium/src/chrome/common/ipc_message.h
+++ b/ipc/chromium/src/chrome/common/ipc_message.h
@@ -52,103 +52,208 @@ class Message : public Pickle {
   };
 
   enum MessageCompression {
     COMPRESSION_NONE,
     COMPRESSION_ENABLED,
     COMPRESSION_ALL
   };
 
+  enum Sync {
+    SYNC = 0,
+    ASYNC = 1,
+  };
+
+  enum Interrupt {
+    NOT_INTERRUPT = 0,
+    INTERRUPT = 1,
+  };
+
+  enum Constructor {
+    NOT_CONSTRUCTOR = 0,
+    CONSTRUCTOR = 1,
+  };
+
+  enum Reply {
+    NOT_REPLY = 0,
+    REPLY = 1,
+  };
+
+  class HeaderFlags {
+    friend class Message;
+
+    enum {
+      NESTED_MASK     = 0x0003,
+      PRIO_MASK       = 0x000C,
+      SYNC_BIT        = 0x0010,
+      REPLY_BIT       = 0x0020,
+      REPLY_ERROR_BIT = 0x0040,
+      INTERRUPT_BIT   = 0x0080,
+      COMPRESS_BIT    = 0x0100,
+      COMPRESSALL_BIT = 0x0200,
+      COMPRESS_MASK   = 0x0300,
+      CONSTRUCTOR_BIT = 0x0400,
+#ifdef MOZ_TASK_TRACER
+      TASKTRACER_BIT  = 0x0800,
+#endif
+    };
+
+  public:
+    constexpr HeaderFlags()
+      : mFlags(NOT_NESTED)
+    {
+    }
+
+    explicit constexpr HeaderFlags(NestedLevel level)
+      : mFlags(level)
+    {
+    }
+
+    constexpr HeaderFlags(NestedLevel level, PriorityValue priority,
+                          MessageCompression compression,
+                          Constructor constructor,
+                          Sync sync, Interrupt interrupt, Reply reply)
+      : mFlags(level |
+               (priority << 2) |
+               (compression == COMPRESSION_ENABLED ? COMPRESS_BIT :
+                compression == COMPRESSION_ALL ? COMPRESSALL_BIT : 0) |
+               (constructor == CONSTRUCTOR ? CONSTRUCTOR_BIT : 0) |
+               (sync == SYNC ? SYNC_BIT : 0) |
+               (interrupt == INTERRUPT ? INTERRUPT_BIT : 0) |
+               (reply == REPLY ? REPLY_BIT : 0))
+    {
+    }
+
+    NestedLevel Level() const {
+      return static_cast<NestedLevel>(mFlags & NESTED_MASK);
+    }
+
+    PriorityValue Priority() const {
+      return static_cast<PriorityValue>((mFlags & PRIO_MASK) >> 2);
+    }
+
+    MessageCompression Compression() const {
+      return ((mFlags & COMPRESS_BIT) ? COMPRESSION_ENABLED :
+              (mFlags & COMPRESSALL_BIT) ? COMPRESSION_ALL : COMPRESSION_NONE);
+    }
+
+    bool IsConstructor() const {
+      return (mFlags & CONSTRUCTOR_BIT) != 0;
+    }
+    bool IsSync() const {
+      return (mFlags & SYNC_BIT) != 0;
+    }
+    bool IsInterrupt() const {
+      return (mFlags & INTERRUPT_BIT) != 0;
+    }
+    bool IsReply() const {
+      return (mFlags & REPLY_BIT) != 0;
+    }
+
+    bool IsReplyError() const {
+      return (mFlags & REPLY_ERROR_BIT) != 0;
+    }
+
+#ifdef MOZ_TASK_TRACER
+    bool IsTaskTracer() const {
+      return (mFlags & TASKTRACER_BIT) != 0;
+    }
+#endif
+
+  private:
+    void SetSync() {
+      mFlags |= SYNC_BIT;
+    }
+    void SetInterrupt() {
+      mFlags |= INTERRUPT_BIT;
+    }
+    void SetReply() {
+      mFlags |= REPLY_BIT;
+    }
+    void SetReplyError() {
+      mFlags |= REPLY_ERROR_BIT;
+    }
+
+#ifdef MOZ_TASK_TRACER
+    void SetTaskTracer() {
+      mFlags |= TASKTRACER_BIT;
+    }
+#endif
+
+    uint32_t mFlags;
+  };
+
   virtual ~Message();
 
   Message();
 
   // Initialize a message with a user-defined type, priority value, and
   // destination WebView ID.
   //
   // NOTE: `recordWriteLatency` is only passed by IPDL generated message code,
   // and is used to trigger the IPC_WRITE_LATENCY_MS telemetry.
   Message(int32_t routing_id,
           msgid_t type,
           uint32_t segmentCapacity = 0, // 0 for the default capacity.
-          NestedLevel nestedLevel = NOT_NESTED,
-          PriorityValue priority = NORMAL_PRIORITY,
-          MessageCompression compression = COMPRESSION_NONE,
+          HeaderFlags flags = HeaderFlags(),
           const char* const name="???",
           bool recordWriteLatency=false);
 
   Message(const char* data, int data_len);
 
   Message(const Message& other) = delete;
   Message(Message&& other);
   Message& operator=(const Message& other) = delete;
   Message& operator=(Message&& other);
 
-  NestedLevel nested_level() const {
-    return static_cast<NestedLevel>(header()->flags & NESTED_MASK);
-  }
+  // Helper method for the common case (default segmentCapacity, recording
+  // the write latency of messages) of IPDL message creation.  This helps
+  // move the malloc and some of the parameter setting out of autogenerated
+  // code.
+  static Message* IPDLMessage(int32_t routing_id,
+                              msgid_t type,
+                              HeaderFlags flags,
+                              const char* const name);
 
-  void set_nested_level(NestedLevel nestedLevel) {
-    DCHECK((nestedLevel & ~NESTED_MASK) == 0);
-    header()->flags = (header()->flags & ~NESTED_MASK) | nestedLevel;
+  // One-off constructors for special error-handling messages.
+  static Message* ForSyncDispatchError(NestedLevel level);
+  static Message* ForInterruptDispatchError();
+
+  NestedLevel nested_level() const {
+    return header()->flags.Level();
   }
 
   PriorityValue priority() const {
-    return static_cast<PriorityValue>((header()->flags & PRIO_MASK) >> 2);
-  }
-
-  void set_priority(PriorityValue prio) {
-    DCHECK(((prio << 2) & ~PRIO_MASK) == 0);
-    header()->flags = (header()->flags & ~PRIO_MASK) | (prio << 2);
+    return header()->flags.Priority();
   }
 
   bool is_constructor() const {
-    return (header()->flags & CONSTRUCTOR_BIT) != 0;
-  }
-
-  void set_constructor() {
-    header()->flags |= CONSTRUCTOR_BIT;
+    return header()->flags.IsConstructor();
   }
 
   // True if this is a synchronous message.
   bool is_sync() const {
-    return (header()->flags & SYNC_BIT) != 0;
+    return header()->flags.IsSync();
   }
 
   // True if this is a synchronous message.
   bool is_interrupt() const {
-    return (header()->flags & INTERRUPT_BIT) != 0;
+    return header()->flags.IsInterrupt();
   }
 
-  // True if compression is enabled for this message.
   MessageCompression compress_type() const {
-    return (header()->flags & COMPRESS_BIT) ?
-               COMPRESSION_ENABLED :
-               (header()->flags & COMPRESSALL_BIT) ?
-                   COMPRESSION_ALL :
-                   COMPRESSION_NONE;
-  }
-
-  // Set this on a reply to a synchronous message.
-  void set_reply() {
-    header()->flags |= REPLY_BIT;
+    return header()->flags.Compression();
   }
 
   bool is_reply() const {
-    return (header()->flags & REPLY_BIT) != 0;
-  }
-
-  // Set this on a reply to a synchronous message to indicate that no receiver
-  // was found.
-  void set_reply_error() {
-    header()->flags |= REPLY_ERROR_BIT;
+    return header()->flags.IsReply();
   }
 
   bool is_reply_error() const {
-    return (header()->flags & REPLY_ERROR_BIT) != 0;
+    return header()->flags.IsReplyError();
   }
 
   msgid_t type() const {
     return header()->type;
   }
 
   int32_t routing_id() const {
     return header()->routing;
@@ -278,24 +383,16 @@ class Message : public Pickle {
 #endif
 #endif
 
 
   friend class Channel;
   friend class MessageReplyDeserializer;
   friend class SyncMessage;
 
-  void set_sync() {
-    header()->flags |= SYNC_BIT;
-  }
-
-  void set_interrupt() {
-    header()->flags |= INTERRUPT_BIT;
-  }
-
 #ifdef MOZ_TASK_TRACER
   void TaskTracerDispatch();
   class AutoTaskTracerRun
     : public mozilla::tasktracer::AutoSaveCurTraceInfo {
     Message& mMsg;
     uint64_t mTaskId;
     uint64_t mSourceEventId;
   public:
@@ -303,36 +400,20 @@ class Message : public Pickle {
     ~AutoTaskTracerRun();
   };
 #endif
 
 #if !defined(OS_MACOSX)
  protected:
 #endif
 
-  // flags
-  enum {
-    NESTED_MASK     = 0x0003,
-    PRIO_MASK       = 0x000C,
-    SYNC_BIT        = 0x0010,
-    REPLY_BIT       = 0x0020,
-    REPLY_ERROR_BIT = 0x0040,
-    INTERRUPT_BIT   = 0x0080,
-    COMPRESS_BIT    = 0x0100,
-    COMPRESSALL_BIT = 0x0200,
-    CONSTRUCTOR_BIT = 0x0400,
-#ifdef MOZ_TASK_TRACER
-    TASKTRACER_BIT  = 0x0800,
-#endif
-  };
-
   struct Header : Pickle::Header {
     int32_t routing;  // ID of the view that this message is destined for
     msgid_t type;   // specifies the user-defined message type
-    uint32_t flags;   // specifies control flags for the message
+    HeaderFlags flags;   // specifies control flags for the message
 #if defined(OS_POSIX)
     uint32_t num_fds; // the number of descriptors included with this message
 # if defined(OS_MACOSX)
     uint32_t cookie;  // cookie to ACK that the descriptors have been read.
 # endif
 #endif
     union {
       // For Interrupt messages, a guess at what the *other* side's stack depth is.
--- a/ipc/glue/MessageChannel.cpp
+++ b/ipc/glue/MessageChannel.cpp
@@ -2086,21 +2086,17 @@ MessageChannel::DispatchSyncMessage(cons
     uint32_t latencyMs = round((TimeStamp::Now() - start).ToMilliseconds());
     if (latencyMs >= kMinTelemetrySyncIPCLatencyMs) {
         Telemetry::Accumulate(Telemetry::IPC_SYNC_RECEIVE_MS,
                               nsDependentCString(aMsg.name()),
                               latencyMs);
     }
 
     if (!MaybeHandleError(rv, aMsg, "DispatchSyncMessage")) {
-        aReply = new Message();
-        aReply->set_sync();
-        aReply->set_nested_level(aMsg.nested_level());
-        aReply->set_reply();
-        aReply->set_reply_error();
+        aReply = Message::ForSyncDispatchError(aMsg.nested_level());
     }
     aReply->set_seqno(aMsg.seqno());
     aReply->set_transaction_id(aMsg.transaction_id());
 }
 
 void
 MessageChannel::DispatchAsyncMessage(const Message& aMsg)
 {
@@ -2147,20 +2143,17 @@ MessageChannel::DispatchInterruptMessage
 
     nsAutoPtr<Message> reply;
 
     ++mRemoteStackDepthGuess;
     Result rv = mListener->OnCallReceived(aMsg, *getter_Transfers(reply));
     --mRemoteStackDepthGuess;
 
     if (!MaybeHandleError(rv, aMsg, "DispatchInterruptMessage")) {
-        reply = new Message();
-        reply->set_interrupt();
-        reply->set_reply();
-        reply->set_reply_error();
+        reply = Message::ForInterruptDispatchError();
     }
     reply->set_seqno(aMsg.seqno());
 
     MonitorAutoLock lock(*mMonitor);
     if (ChannelConnected == mChannelState) {
         mLink->SendMessage(reply.forget());
     }
 }
--- a/ipc/glue/ProtocolUtils.cpp
+++ b/ipc/glue/ProtocolUtils.cpp
@@ -72,17 +72,17 @@ class ChannelOpened : public IPC::Messag
 public:
   ChannelOpened(TransportDescriptor aDescriptor,
                 ProcessId aOtherProcess,
                 ProtocolId aProtocol,
                 NestedLevel aNestedLevel = NOT_NESTED)
     : IPC::Message(MSG_ROUTING_CONTROL, // these only go to top-level actors
                    CHANNEL_OPENED_MESSAGE_TYPE,
                    0,
-                   aNestedLevel)
+                   HeaderFlags(aNestedLevel))
   {
     IPC::WriteParam(this, aDescriptor);
     IPC::WriteParam(this, aOtherProcess);
     IPC::WriteParam(this, static_cast<uint32_t>(aProtocol));
   }
 
   static bool Read(const IPC::Message& aMsg,
                    TransportDescriptor* aDescriptor,
--- a/ipc/glue/Shmem.cpp
+++ b/ipc/glue/Shmem.cpp
@@ -20,17 +20,18 @@ class ShmemCreated : public IPC::Message
 private:
   typedef Shmem::id_t id_t;
 
 public:
   ShmemCreated(int32_t routingId,
                id_t aIPDLId,
                size_t aSize,
                SharedMemory::SharedMemoryType aType) :
-    IPC::Message(routingId, SHMEM_CREATED_MESSAGE_TYPE, 0, NESTED_INSIDE_CPOW)
+    IPC::Message(routingId, SHMEM_CREATED_MESSAGE_TYPE, 0,
+                 HeaderFlags(NESTED_INSIDE_CPOW))
   {
     IPC::WriteParam(this, aIPDLId);
     IPC::WriteParam(this, aSize);
     IPC::WriteParam(this, int32_t(aType));
   }
 
   static bool
   ReadInfo(const Message* msg, PickleIterator* iter,
--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -1592,34 +1592,24 @@ class _GenerateProtocolCode(ipdl.ast.Vis
 
             # Look up the segment capacity used for serializing this
             # message. If the capacity is not specified, use '0' for
             # the default capacity (defined in ipc_message.cc)
             name = '%s::%s' % (md.namespace, md.decl.progname)
             segmentcapacity = self.segmentcapacitydict.get(name, 0)
 
             mfDecl, mfDefn = _splitFuncDeclDefn(
-                _generateMessageConstructor(md.msgCtorFunc(), md.msgId(),
-                                            segmentcapacity,
-                                            md.decl.type.nested,
-                                            md.decl.type.prio,
-                                            md.prettyMsgName(p.name+'::'),
-                                            md.decl.type.compress))
+                _generateMessageConstructor(md, segmentcapacity, p,
+                                            forReply=False))
             decls.append(mfDecl)
             self.funcDefns.append(mfDefn)
 
             if md.hasReply():
                 rfDecl, rfDefn = _splitFuncDeclDefn(
-                    _generateMessageConstructor(
-                        md.replyCtorFunc(), md.replyId(),
-                        0,
-                        md.decl.type.nested,
-                        md.decl.type.prio,
-                        md.prettyReplyName(p.name+'::'),
-                        md.decl.type.compress))
+                    _generateMessageConstructor(md, 0, p, forReply=True))
                 decls.append(rfDecl)
                 self.funcDefns.append(rfDefn)
 
             decls.append(Whitespace.NL)
             ns.addstmts(decls)
 
         ns.addstmts([ Whitespace.NL, Whitespace.NL ])
 
@@ -1706,58 +1696,107 @@ class _GenerateProtocolCode(ipdl.ast.Vis
         fromswitch.addcase(DefaultLabel(), unreachedblock)
 
         transitionfunc.addstmt(fromswitch)
 
         return transitionfunc
 
 ##--------------------------------------------------
 
-def _generateMessageConstructor(clsname, msgid, segmentSize, nested, prio, prettyName, compress):
+def _generateMessageConstructor(md, segmentSize, protocol, forReply=False):
+    if forReply:
+        clsname = md.replyCtorFunc()
+        msgid = md.replyId()
+        prettyName = md.prettyReplyName(protocol.name+'::')
+        replyEnum = 'REPLY'
+    else:
+        clsname = md.msgCtorFunc()
+        msgid = md.msgId()
+        prettyName = md.prettyMsgName(protocol.name+'::')
+        replyEnum = 'NOT_REPLY'
+
+    nested = md.decl.type.nested
+    prio = md.decl.type.prio
+    compress = md.decl.type.compress
+
     routingId = ExprVar('routingId')
 
     func = FunctionDefn(FunctionDecl(
         clsname,
         params=[ Decl(Type('int32_t'), routingId.name) ],
         ret=Type('IPC::Message', ptr=1)))
 
     if compress == 'compress':
-        compression = ExprVar('IPC::Message::COMPRESSION_ENABLED')
+        compression = 'COMPRESSION_ENABLED'
     elif compress:
         assert compress == 'compressall'
-        compression = ExprVar('IPC::Message::COMPRESSION_ALL')
+        compression = 'COMPRESSION_ALL'
     else:
-        compression = ExprVar('IPC::Message::COMPRESSION_NONE')
+        compression = 'COMPRESSION_NONE'
 
     if nested == ipdl.ast.NOT_NESTED:
-        nestedEnum = 'IPC::Message::NOT_NESTED'
+        nestedEnum = 'NOT_NESTED'
     elif nested == ipdl.ast.INSIDE_SYNC_NESTED:
-        nestedEnum = 'IPC::Message::NESTED_INSIDE_SYNC'
+        nestedEnum = 'NESTED_INSIDE_SYNC'
     else:
         assert nested == ipdl.ast.INSIDE_CPOW_NESTED
-        nestedEnum = 'IPC::Message::NESTED_INSIDE_CPOW'
+        nestedEnum = 'NESTED_INSIDE_CPOW'
 
     if prio == ipdl.ast.NORMAL_PRIORITY:
-        prioEnum = 'IPC::Message::NORMAL_PRIORITY'
+        prioEnum = 'NORMAL_PRIORITY'
     elif prio == ipdl.ast.INPUT_PRIORITY:
-        prioEnum = 'IPC::Message::INPUT_PRIORITY'
+        prioEnum = 'INPUT_PRIORITY'
+    else:
+        prioEnum = 'HIGH_PRIORITY'
+
+    if md.decl.type.isSync():
+        syncEnum = 'SYNC'
+    else:
+        syncEnum = 'ASYNC'
+
+    if md.decl.type.isInterrupt():
+        interruptEnum = 'INTERRUPT'
+    else:
+        interruptEnum = 'NOT_INTERRUPT'
+
+    if md.decl.type.isCtor():
+        ctorEnum = 'CONSTRUCTOR'
     else:
-        prioEnum = 'IPC::Message::HIGH_PRIORITY'
-
-    func.addstmt(
-        StmtReturn(ExprNew(Type('IPC::Message'),
-                           args=[ routingId,
-                                  ExprVar(msgid),
-                                  ExprLiteral.Int(int(segmentSize)),
-                                  ExprVar(nestedEnum),
-                                  ExprVar(prioEnum),
-                                  compression,
-                                  ExprLiteral.String(prettyName),
-                                  # Pass `true` to recordWriteLatency to collect telemetry
-                                  ExprLiteral.TRUE ])))
+        ctorEnum = 'NOT_CONSTRUCTOR'
+
+    def messageEnum(valname):
+        return ExprVar('IPC::Message::' + valname)
+
+    flags = ExprCall(ExprVar('IPC::Message::HeaderFlags'),
+                     args=[ messageEnum(nestedEnum),
+                            messageEnum(prioEnum),
+                            messageEnum(compression),
+                            messageEnum(ctorEnum),
+                            messageEnum(syncEnum),
+                            messageEnum(interruptEnum),
+                            messageEnum(replyEnum) ])
+
+    segmentSize = int(segmentSize)
+    if segmentSize:
+        func.addstmt(
+            StmtReturn(ExprNew(Type('IPC::Message'),
+                               args=[ routingId,
+                                      ExprVar(msgid),
+                                      ExprLiteral.Int(int(segmentSize)),
+                                      flags,
+                                      ExprLiteral.String(prettyName),
+                                      # Pass `true` to recordWriteLatency to collect telemetry
+                                      ExprLiteral.TRUE ])))
+    else:
+        func.addstmt(
+            StmtReturn(ExprCall(ExprVar('IPC::Message::IPDLMessage'),
+                               args=[ routingId,
+                                      ExprVar(msgid),
+                                      flags,
+                                      ExprLiteral.String(prettyName) ])))
 
     return func
 
 ##--------------------------------------------------
 
 class _ComputeTypeDeps(TypeVisitor):
     '''Pass that gathers the C++ types that a particular IPDL type
 (recursively) depends on.  There are two kinds of dependencies: (i)
@@ -4268,34 +4307,34 @@ class _GenerateProtocolActorCode(ipdl.as
 
         stmts = ([ StmtDecl(Decl(Type('IPC::Message', ptr=1), msgvar.name),
                             init=ExprCall(ExprVar(md.pqMsgCtorFunc()),
                                           args=[ routingId ])) ]
                  + [ Whitespace.NL ]
                  + [ self.checkedWrite(p.ipdltype, p.var(), msgvar, sentinelKey=p.name, this=this)
                      for p in md.params ]
                  + [ Whitespace.NL ]
-                 + self.setMessageFlags(md, msgvar, reply=0))
+                 + self.setMessageFlags(md, msgvar))
         return msgvar, stmts
 
 
     def makeResolver(self, md, errfn, routingId):
         if routingId is None:
             routingId = self.protocol.routingId()
         if not md.decl.type.isAsync() or not md.hasReply():
             return [ ]
 
         sendok = ExprVar('sendok__')
         seqno = ExprVar('seqno__')
         resolve = ExprVar('resolve__')
         reason = ExprVar('reason__')
         resolvertype = Type(md.resolverName())
         failifsendok = StmtIf(ExprNot(sendok))
         failifsendok.addifstmt(_printWarningMessage('Error sending reply'))
-        sendmsg = (self.setMessageFlags(md, self.replyvar, reply=1, seqno=seqno)
+        sendmsg = (self.setMessageFlags(md, self.replyvar, seqno=seqno)
                    + [ self.logMessage(md, self.replyvar, 'Sending reply '),
                        StmtDecl(Decl(Type.BOOL, sendok.name),
                                 init=ExprCall(
                                     ExprSelect(self.protocol.callGetChannel(),
                                                '->', 'Send'),
                                     args=[ self.replyvar ])),
                        failifsendok ])
         if len(md.returns) > 1:
@@ -4356,17 +4395,17 @@ class _GenerateProtocolActorCode(ipdl.as
 
         replyvar = self.replyvar
         return (
             [ StmtExpr(ExprAssn(
                 replyvar, ExprCall(ExprVar(md.pqReplyCtorFunc()), args=[ routingId ]))),
               Whitespace.NL ]
             + [ self.checkedWrite(r.ipdltype, r.var(), replyvar, sentinelKey=r.name)
                 for r in md.returns ]
-            + self.setMessageFlags(md, replyvar, reply=1)
+            + self.setMessageFlags(md, replyvar)
             + [ self.logMessage(md, replyvar, 'Sending reply ') ])
 
     def genVerifyMessage(self, verify, params, errfn, msgsrcVar):
         stmts = [ ]
         if not verify:
             return stmts
         if len(params) == 0:
             return stmts
@@ -4399,34 +4438,19 @@ class _GenerateProtocolActorCode(ipdl.as
                 for p in params ]
             + [ self.endRead(msgvar, itervar) ]
             # Move the message back to its source before sending.
             + [ StmtExpr(ExprAssn(ExprDeref(msgsrcVar), ExprMove(msgvar))) ]
             ))
 
         return stmts
 
-    def setMessageFlags(self, md, var, reply, seqno=None):
+    def setMessageFlags(self, md, var, seqno=None):
         stmts = [ ]
 
-        if md.decl.type.isSync():
-            stmts.append(StmtExpr(ExprCall(
-                ExprSelect(var, '->', 'set_sync'))))
-        elif md.decl.type.isInterrupt():
-            stmts.append(StmtExpr(ExprCall(
-                ExprSelect(var, '->', 'set_interrupt'))))
-
-        if md.decl.type.isCtor():
-            stmts.append(StmtExpr(ExprCall(
-                ExprSelect(var, '->', 'set_constructor'))))
-
-        if reply:
-            stmts.append(StmtExpr(ExprCall(
-                ExprSelect(var, '->', 'set_reply'))))
-
         if seqno:
             stmts.append(StmtExpr(ExprCall(
                 ExprSelect(var, '->', 'set_seqno'),
                 args=[ seqno ])))
 
         return stmts + [ Whitespace.NL ]
 
 
--- a/js/public/Value.h
+++ b/js/public/Value.h
@@ -209,20 +209,23 @@ typedef enum JSWhyMagic
     JS_UNINITIALIZED_LEXICAL,
 
     /** for local use */
     JS_GENERIC_MAGIC,
 
     JS_WHY_MAGIC_COUNT
 } JSWhyMagic;
 
+namespace js {
+static inline JS::Value PoisonedObjectValue(uintptr_t poison);
+} // namespace js
+
 namespace JS {
 
 static inline constexpr JS::Value UndefinedValue();
-static inline JS::Value PoisonedObjectValue(JSObject* obj);
 
 namespace detail {
 
 constexpr int CanonicalizedNaNSignBit = 0;
 constexpr uint64_t CanonicalizedNaNSignificand = 0x8000000000000ULL;
 
 constexpr uint64_t CanonicalizedNaNBits =
     mozilla::SpecificNaNBits<double,
@@ -356,33 +359,33 @@ class MOZ_NON_PARAM alignas(8) Value
     }
 
     void setSymbol(JS::Symbol* sym) {
         MOZ_ASSERT(uintptr_t(sym) > 0x1000);
         data.asBits = bitsFromTagAndPayload(JSVAL_TAG_SYMBOL, PayloadType(sym));
     }
 
     void setObject(JSObject& obj) {
-        MOZ_ASSERT(uintptr_t(&obj) > 0x1000 || uintptr_t(&obj) == 0x48);
+        MOZ_ASSERT(uintptr_t(&obj) >= 0x1000);
 #if defined(JS_PUNBOX64)
         // VisualStudio cannot contain parenthesized C++ style cast and shift
         // inside decltype in template parameter:
         //   AssertionConditionType<decltype((uintptr_t(x) >> 1))>
         // It throws syntax error.
         MOZ_ASSERT((((uintptr_t)&obj) >> JSVAL_TAG_SHIFT) == 0);
 #endif
         setObjectNoCheck(&obj);
     }
 
   private:
     void setObjectNoCheck(JSObject* obj) {
         data.asBits = bitsFromTagAndPayload(JSVAL_TAG_OBJECT, PayloadType(obj));
     }
 
-    friend inline Value PoisonedObjectValue(JSObject* obj);
+    friend inline Value js::PoisonedObjectValue(uintptr_t poison);
 
   public:
     void setBoolean(bool b) {
         data.asBits = bitsFromTagAndPayload(JSVAL_TAG_BOOLEAN, uint32_t(b));
     }
 
     void setMagic(JSWhyMagic why) {
         data.asBits = bitsFromTagAndPayload(JSVAL_TAG_MAGIC, uint32_t(why));
@@ -1077,24 +1080,16 @@ static inline Value
 ObjectValue(JSObject& obj)
 {
     Value v;
     v.setObject(obj);
     return v;
 }
 
 static inline Value
-ObjectValueCrashOnTouch()
-{
-    Value v;
-    v.setObject(*reinterpret_cast<JSObject*>(0x48));
-    return v;
-}
-
-static inline Value
 MagicValue(JSWhyMagic why)
 {
     Value v;
     v.setMagic(why);
     return v;
 }
 
 static inline Value
@@ -1230,24 +1225,16 @@ PrivateUint32Value(uint32_t ui)
 static inline Value
 PrivateGCThingValue(js::gc::Cell* cell)
 {
     Value v;
     v.setPrivateGCThing(cell);
     return v;
 }
 
-static inline Value
-PoisonedObjectValue(JSObject* obj)
-{
-    Value v;
-    v.setObjectNoCheck(obj);
-    return v;
-}
-
 inline bool
 SameType(const Value& lhs, const Value& rhs)
 {
 #if defined(JS_NUNBOX32)
     JSValueTag ltag = lhs.toTag(), rtag = rhs.toTag();
     return ltag == rtag || (ltag < JSVAL_TAG_CLEAR && rtag < JSVAL_TAG_CLEAR);
 #elif defined(JS_PUNBOX64)
     return (lhs.isDouble() && rhs.isDouble()) ||
@@ -1449,16 +1436,24 @@ DispatchTyped(F f, const JS::Value& val,
     MOZ_ASSERT(!val.isGCThing());
     return F::defaultValue(val);
 }
 
 template <class S> struct VoidDefaultAdaptor { static void defaultValue(const S&) {} };
 template <class S> struct IdentityDefaultAdaptor { static S defaultValue(const S& v) {return v;} };
 template <class S, bool v> struct BoolDefaultAdaptor { static bool defaultValue(const S&) { return v; } };
 
+static inline JS::Value
+PoisonedObjectValue(uintptr_t poison)
+{
+    JS::Value v;
+    v.setObjectNoCheck(reinterpret_cast<JSObject*>(poison));
+    return v;
+}
+
 } // namespace js
 
 #ifdef DEBUG
 namespace JS {
 
 MOZ_ALWAYS_INLINE bool
 ValueIsNotGray(const Value& value)
 {
--- a/js/src/jsapi-tests/testGCStoreBufferRemoval.cpp
+++ b/js/src/jsapi-tests/testGCStoreBufferRemoval.cpp
@@ -61,31 +61,31 @@ BEGIN_TEST(testGCStoreBufferRemoval)
 
     // Test removal of store buffer entries added by HeapPtr<Value>.
     {
         Value punnedValue;
         HeapPtr<Value>* relocValue = reinterpret_cast<HeapPtr<Value>*>(&punnedValue);
         new (relocValue) HeapPtr<Value>;
         *relocValue = ObjectValue(*NurseryObject());
         relocValue->~HeapPtr<Value>();
-        punnedValue = ObjectValueCrashOnTouch();
+        punnedValue = js::PoisonedObjectValue(0x48);
         JS_GC(cx);
 
         new (relocValue) HeapPtr<Value>;
         *relocValue = ObjectValue(*NurseryObject());
         *relocValue = ObjectValue(*tenuredObject);
         relocValue->~HeapPtr<Value>();
-        punnedValue = ObjectValueCrashOnTouch();
+        punnedValue = js::PoisonedObjectValue(0x48);
         JS_GC(cx);
 
         new (relocValue) HeapPtr<Value>;
         *relocValue = ObjectValue(*NurseryObject());
         *relocValue = NullValue();
         relocValue->~HeapPtr<Value>();
-        punnedValue = ObjectValueCrashOnTouch();
+        punnedValue = js::PoisonedObjectValue(0x48);
         JS_GC(cx);
     }
 
     // Test removal of store buffer entries added by Heap<T>.
     {
         JSObject* badObject = reinterpret_cast<JSObject*>(1);
         JSObject* punnedPtr = nullptr;
         Heap<JSObject*>* heapPtr =
--- a/js/src/jsutil.h
+++ b/js/src/jsutil.h
@@ -304,22 +304,22 @@ Poison(void* ptr, uint8_t value, size_t 
         return ptr;
 
     // Without a valid Value tag, a poisoned Value may look like a valid
     // floating point number. To ensure that we crash more readily when
     // observing a poisoned Value, we make the poison an invalid ObjectValue.
     // Unfortunately, this adds about 2% more overhead, so we can only enable
     // it in debug.
 #if defined(DEBUG)
-    uintptr_t obj;
-    memset(&obj, value, sizeof(obj));
+    uintptr_t poison;
+    memset(&poison, value, sizeof(poison));
 # if defined(JS_PUNBOX64)
-    obj = obj & ((uintptr_t(1) << JSVAL_TAG_SHIFT) - 1);
+    poison = poison & ((uintptr_t(1) << JSVAL_TAG_SHIFT) - 1);
 # endif
-    JS::Value v = JS::PoisonedObjectValue(reinterpret_cast<JSObject*>(obj));
+    JS::Value v = js::PoisonedObjectValue(poison);
 
     size_t value_count = num / sizeof(v);
     size_t byte_count = num % sizeof(v);
     mozilla::PodSet(reinterpret_cast<JS::Value*>(ptr), v, value_count);
     if (byte_count) {
         uint8_t* bytes = static_cast<uint8_t*>(ptr);
         uint8_t* end = bytes + num;
         mozilla::PodSet(end - byte_count, value, byte_count);
--- a/js/src/vm/NativeObject.h
+++ b/js/src/vm/NativeObject.h
@@ -36,17 +36,17 @@ class TenuringTracer;
  * in debug builds and crash in release builds. Instead, we use a safe-for-crash
  * pointer.
  */
 static MOZ_ALWAYS_INLINE void
 Debug_SetValueRangeToCrashOnTouch(Value* beg, Value* end)
 {
 #ifdef DEBUG
     for (Value* v = beg; v != end; ++v)
-        v->setObject(*reinterpret_cast<JSObject*>(0x48));
+        *v = js::PoisonedObjectValue(0x48);
 #endif
 }
 
 static MOZ_ALWAYS_INLINE void
 Debug_SetValueRangeToCrashOnTouch(Value* vec, size_t len)
 {
 #ifdef DEBUG
     Debug_SetValueRangeToCrashOnTouch(vec, vec + len);
--- a/js/src/vm/RegExpShared.h
+++ b/js/src/vm/RegExpShared.h
@@ -111,17 +111,17 @@ class RegExpShared : public gc::TenuredC
         RegExpCompilation() : byteCode(nullptr) {}
 
         bool compiled(ForceByteCodeEnum force = DontForceByteCode) const {
             return byteCode || (force == DontForceByteCode && jitCode);
         }
     };
 
     /* Source to the RegExp, for lazy compilation. */
-    HeapPtr<JSAtom*>   source;
+    GCPtr<JSAtom*>     source;
 
     RegExpFlag         flags;
     bool               canStringMatch;
     size_t             parenCount;
 
     RegExpCompilation  compilationArray[4];
 
     static int CompilationIndex(CompilationMode mode, bool latin1) {
--- a/layout/painting/FrameLayerBuilder.cpp
+++ b/layout/painting/FrameLayerBuilder.cpp
@@ -470,20 +470,20 @@ public:
    * Record that an item has been added to the PaintedLayer, so we
    * need to update our regions.
    * @param aVisibleRect the area of the item that's visible
    * @param aSolidColor if non-null, the visible area of the item is
    * a constant color given by *aSolidColor
    */
   void Accumulate(ContainerState* aState,
                   nsDisplayItem* aItem,
-                  const nsIntRegion& aClippedOpaqueRegion,
                   const nsIntRect& aVisibleRect,
                   const DisplayItemClip& aClip,
-                  LayerState aLayerState);
+                  LayerState aLayerState,
+                  nsDisplayList *aList);
   AnimatedGeometryRoot* GetAnimatedGeometryRoot() { return mAnimatedGeometryRoot; }
 
   /**
    * A region including the horizontal pan, vertical pan, and no action regions.
    */
   nsRegion CombinedTouchActionRegion();
 
   /**
@@ -3426,20 +3426,20 @@ IsItemAreaInWindowOpaqueRegion(nsDisplay
     return false;
   }
   return aBuilder->GetWindowOpaqueRegion().Contains(aComponentAlphaBounds);
 }
 
 void
 PaintedLayerData::Accumulate(ContainerState* aState,
                             nsDisplayItem* aItem,
-                            const nsIntRegion& aClippedOpaqueRegion,
                             const nsIntRect& aVisibleRect,
                             const DisplayItemClip& aClip,
-                            LayerState aLayerState)
+                            LayerState aLayerState,
+                            nsDisplayList* aList)
 {
   FLB_LOG_PAINTED_LAYER_DECISION(this, "Accumulating dp=%s(%p), f=%p against pld=%p\n", aItem->Name(), aItem, aItem->Frame(), this);
 
   if (aState->mBuilder->NeedToForceTransparentSurfaceForItem(aItem)) {
     mForceTransparentSurface = true;
   }
   if (aState->mParameters.mDisableSubpixelAntialiasingInDescendants) {
     // Disable component alpha.
@@ -3465,21 +3465,26 @@ PaintedLayerData::Accumulate(ContainerSt
     // The rest of this method won't do anything. mVisibleRegion and mOpaqueRegion
     // don't need updating. mVisibleRegion contains aVisibleRect already,
     // mOpaqueRegion contains aVisibleRect and therefore whatever the opaque
     // region of the item is. mVisibleRegion must contain mOpaqueRegion
     // and therefore aVisibleRect.
     return;
   }
 
+  nsIntRegion opaquePixels = aState->ComputeOpaqueRect(aItem,
+                                                       mAnimatedGeometryRoot, mASR, aClip, aList,
+                                                       &mHideAllLayersBelow, &mOpaqueForAnimatedGeometryRootParent);
+  opaquePixels.AndWith(aVisibleRect);
+
   /* Mark as available for conversion to image layer if this is a nsDisplayImage and
    * it's the only thing visible in this layer.
    */
   if (nsIntRegion(aVisibleRect).Contains(mVisibleRegion) &&
-      aClippedOpaqueRegion.Contains(mVisibleRegion) &&
+      opaquePixels.Contains(mVisibleRegion) &&
       aItem->SupportsOptimizingToImage()) {
     mImage = static_cast<nsDisplayImageContainer*>(aItem);
     FLB_LOG_PAINTED_LAYER_DECISION(this, "  Tracking image: nsDisplayImageContainer covers the layer\n");
   } else if (mImage) {
     FLB_LOG_PAINTED_LAYER_DECISION(this, "  No longer tracking image\n");
     mImage = nullptr;
   }
 
@@ -3520,18 +3525,18 @@ PaintedLayerData::Accumulate(ContainerSt
       FLB_LOG_PAINTED_LAYER_DECISION(this, "  Layer is not a solid color: Display item is not uniform over the visible bound\n");
       mIsSolidColorInVisibleRegion = false;
     }
 
     mVisibleRegion.Or(mVisibleRegion, aVisibleRect);
     mVisibleRegion.SimplifyOutward(4);
   }
 
-  if (!aClippedOpaqueRegion.IsEmpty()) {
-    for (auto iter = aClippedOpaqueRegion.RectIter(); !iter.Done(); iter.Next()) {
+  if (!opaquePixels.IsEmpty()) {
+    for (auto iter = opaquePixels.RectIter(); !iter.Done(); iter.Next()) {
       // We don't use SimplifyInward here since it's not defined exactly
       // what it will discard. For our purposes the most important case
       // is a large opaque background at the bottom of z-order (e.g.,
       // a canvas background), so we need to make sure that the first rect
       // we see doesn't get discarded.
       nsIntRegion tmp;
       tmp.Or(mOpaqueRegion, iter.Get());
        // Opaque display items in chrome documents whose window is partially
@@ -4481,24 +4486,17 @@ ContainerState::ProcessDisplayItems(nsDi
             static_cast<nsDisplayLayerEventRegions*>(item);
         paintedLayerData->AccumulateEventRegions(this, eventRegions);
       } else {
         // check to see if the new item has rounded rect clips in common with
         // other items in the layer
         if (mManager->IsWidgetLayerManager()) {
           paintedLayerData->UpdateCommonClipCount(itemClip);
         }
-        nsIntRegion opaquePixels = ComputeOpaqueRect(item,
-            animatedGeometryRoot, itemASR, itemClip, aList,
-            &paintedLayerData->mHideAllLayersBelow,
-            &paintedLayerData->mOpaqueForAnimatedGeometryRootParent);
-        MOZ_ASSERT(nsIntRegion(itemDrawRect).Contains(opaquePixels));
-        opaquePixels.AndWith(itemVisibleRect);
-        paintedLayerData->Accumulate(this, item, opaquePixels,
-            itemVisibleRect, itemClip, layerState);
+        paintedLayerData->Accumulate(this, item, itemVisibleRect, itemClip, layerState, aList);
 
         if (!paintedLayerData->mLayer) {
           // Try to recycle the old layer of this display item.
           RefPtr<PaintedLayer> layer =
             AttemptToRecyclePaintedLayer(animatedGeometryRoot, item, aTopLeft);
           if (layer) {
             paintedLayerData->mLayer = layer;
 
--- a/layout/painting/nsDisplayItemTypes.h
+++ b/layout/painting/nsDisplayItemTypes.h
@@ -13,56 +13,50 @@
  */
 
 #ifndef NSDISPLAYITEMTYPES_H_
 #define NSDISPLAYITEMTYPES_H_
 
 enum class DisplayItemType {
   TYPE_ZERO = 0, /** Spacer so that the first item starts at 1 */
 
-#define DECLARE_DISPLAY_ITEM_TYPE(name) TYPE_##name,
-#define DECLARE_DISPLAY_ITEM_TYPE_FLAGS(name,flags) TYPE_##name,
+#define DECLARE_DISPLAY_ITEM_TYPE(name,flags) TYPE_##name,
 #include "nsDisplayItemTypesList.h"
 #undef DECLARE_DISPLAY_ITEM_TYPE
-#undef DECLARE_DISPLAY_ITEM_TYPE_FLAGS
 
   TYPE_MAX
 };
 
 enum {
   // Number of bits needed to represent all types
   TYPE_BITS = 8
 };
 
 enum DisplayItemFlags {
   TYPE_RENDERS_NO_IMAGES = 1 << 0
 };
 
 inline const char* DisplayItemTypeName(DisplayItemType aType)
 {
   switch (aType) {
-#define DECLARE_DISPLAY_ITEM_TYPE(name) case DisplayItemType::TYPE_##name: return #name;
-#define DECLARE_DISPLAY_ITEM_TYPE_FLAGS(name,flags) case DisplayItemType::TYPE_##name: return #name;
+#define DECLARE_DISPLAY_ITEM_TYPE(name,flags) case DisplayItemType::TYPE_##name: return #name;
 #include "nsDisplayItemTypesList.h"
 #undef DECLARE_DISPLAY_ITEM_TYPE
-#undef DECLARE_DISPLAY_ITEM_TYPE_FLAGS
 
     default: return "TYPE_UNKNOWN";
   }
 }
 
 inline uint8_t GetDisplayItemFlagsForType(DisplayItemType aType)
 {
   static const uint8_t flags[static_cast<uint32_t>(DisplayItemType::TYPE_MAX)] = {
     0
-#define DECLARE_DISPLAY_ITEM_TYPE(name) ,0
-#define DECLARE_DISPLAY_ITEM_TYPE_FLAGS(name,flags) ,flags
+#define DECLARE_DISPLAY_ITEM_TYPE(name,flags) ,flags
 #include "nsDisplayItemTypesList.h"
 #undef DECLARE_DISPLAY_ITEM_TYPE
-#undef DECLARE_DISPLAY_ITEM_TYPE_FLAGS
   };
 
   return flags[static_cast<uint32_t>(aType)];
 }
 
 inline DisplayItemType GetDisplayItemTypeFromKey(uint32_t aDisplayItemKey)
 {
   static const uint32_t typeMask = (1 << TYPE_BITS) - 1;
--- a/layout/painting/nsDisplayItemTypesList.h
+++ b/layout/painting/nsDisplayItemTypesList.h
@@ -1,99 +1,101 @@
 // IWYU pragma: private, include "nsDisplayList.h"
-DECLARE_DISPLAY_ITEM_TYPE(ALT_FEEDBACK)
-DECLARE_DISPLAY_ITEM_TYPE(BACKGROUND)
-DECLARE_DISPLAY_ITEM_TYPE(THEMED_BACKGROUND)
-DECLARE_DISPLAY_ITEM_TYPE_FLAGS(BACKGROUND_COLOR,TYPE_RENDERS_NO_IMAGES)
-DECLARE_DISPLAY_ITEM_TYPE(BLEND_CONTAINER)
-DECLARE_DISPLAY_ITEM_TYPE(BLEND_MODE)
-DECLARE_DISPLAY_ITEM_TYPE(BORDER)
-DECLARE_DISPLAY_ITEM_TYPE(BOX_SHADOW_OUTER)
-DECLARE_DISPLAY_ITEM_TYPE(BOX_SHADOW_INNER)
-DECLARE_DISPLAY_ITEM_TYPE(BULLET)
-DECLARE_DISPLAY_ITEM_TYPE(BUTTON_BORDER_BACKGROUND)
-DECLARE_DISPLAY_ITEM_TYPE(BUTTON_BOX_SHADOW_OUTER)
-DECLARE_DISPLAY_ITEM_TYPE(BUTTON_FOREGROUND)
-DECLARE_DISPLAY_ITEM_TYPE(CANVAS)
-DECLARE_DISPLAY_ITEM_TYPE(CANVAS_BACKGROUND_COLOR)
-DECLARE_DISPLAY_ITEM_TYPE(CANVAS_THEMED_BACKGROUND)
-DECLARE_DISPLAY_ITEM_TYPE(CANVAS_BACKGROUND_IMAGE)
-DECLARE_DISPLAY_ITEM_TYPE(CANVAS_FOCUS)
-DECLARE_DISPLAY_ITEM_TYPE(CARET)
-DECLARE_DISPLAY_ITEM_TYPE(CHECKED_CHECKBOX)
-DECLARE_DISPLAY_ITEM_TYPE(CHECKED_RADIOBUTTON)
-DECLARE_DISPLAY_ITEM_TYPE(CLEAR_BACKGROUND)
-DECLARE_DISPLAY_ITEM_TYPE(COLUMN_RULE)
-DECLARE_DISPLAY_ITEM_TYPE(COMBOBOX_FOCUS)
-DECLARE_DISPLAY_ITEM_TYPE(EVENT_RECEIVER)
-DECLARE_DISPLAY_ITEM_TYPE(LAYER_EVENT_REGIONS)
-DECLARE_DISPLAY_ITEM_TYPE(FIELDSET_BORDER_BACKGROUND)
-DECLARE_DISPLAY_ITEM_TYPE(FIXED_POSITION)
-DECLARE_DISPLAY_ITEM_TYPE(STICKY_POSITION)
-DECLARE_DISPLAY_ITEM_TYPE(FRAMESET_BORDER)
-DECLARE_DISPLAY_ITEM_TYPE(FRAMESET_BLANK)
-DECLARE_DISPLAY_ITEM_TYPE(HEADER_FOOTER)
-DECLARE_DISPLAY_ITEM_TYPE(IMAGE)
-DECLARE_DISPLAY_ITEM_TYPE(LIST_FOCUS)
-DECLARE_DISPLAY_ITEM_TYPE(OPACITY)
-DECLARE_DISPLAY_ITEM_TYPE(OPTION_EVENT_GRABBER)
-DECLARE_DISPLAY_ITEM_TYPE(OUTLINE)
-DECLARE_DISPLAY_ITEM_TYPE(OWN_LAYER)
-DECLARE_DISPLAY_ITEM_TYPE(PLUGIN)
-DECLARE_DISPLAY_ITEM_TYPE(PLUGIN_READBACK)
-DECLARE_DISPLAY_ITEM_TYPE(PLUGIN_VIDEO)
-DECLARE_DISPLAY_ITEM_TYPE(PRINT_PLUGIN)
-DECLARE_DISPLAY_ITEM_TYPE(RANGE_FOCUS_RING)
-DECLARE_DISPLAY_ITEM_TYPE(REMOTE)
-DECLARE_DISPLAY_ITEM_TYPE(RESOLUTION)
-DECLARE_DISPLAY_ITEM_TYPE(SCROLL_INFO_LAYER)
-DECLARE_DISPLAY_ITEM_TYPE(SELECTION_OVERLAY)
-DECLARE_DISPLAY_ITEM_TYPE(SOLID_COLOR)
-DECLARE_DISPLAY_ITEM_TYPE(SOLID_COLOR_REGION)
-DECLARE_DISPLAY_ITEM_TYPE(SUBDOCUMENT)
-DECLARE_DISPLAY_ITEM_TYPE(MASK)
-DECLARE_DISPLAY_ITEM_TYPE(FILTER)
-DECLARE_DISPLAY_ITEM_TYPE(SVG_OUTER_SVG)
-DECLARE_DISPLAY_ITEM_TYPE(SVG_GEOMETRY)
-DECLARE_DISPLAY_ITEM_TYPE(SVG_TEXT)
-DECLARE_DISPLAY_ITEM_TYPE(TABLE_CELL_BACKGROUND)
-DECLARE_DISPLAY_ITEM_TYPE(TABLE_CELL_SELECTION)
-DECLARE_DISPLAY_ITEM_TYPE(TABLE_BORDER_COLLAPSE)
-DECLARE_DISPLAY_ITEM_TYPE(TEXT)
-DECLARE_DISPLAY_ITEM_TYPE(TEXT_OVERFLOW)
-DECLARE_DISPLAY_ITEM_TYPE_FLAGS(TRANSFORM,TYPE_RENDERS_NO_IMAGES)
-DECLARE_DISPLAY_ITEM_TYPE_FLAGS(PERSPECTIVE,TYPE_RENDERS_NO_IMAGES)
-DECLARE_DISPLAY_ITEM_TYPE(VIDEO)
-DECLARE_DISPLAY_ITEM_TYPE(WRAP_LIST)
-DECLARE_DISPLAY_ITEM_TYPE(ZOOM)
-DECLARE_DISPLAY_ITEM_TYPE(GENERIC)
+DECLARE_DISPLAY_ITEM_TYPE(ALT_FEEDBACK, 0)
+DECLARE_DISPLAY_ITEM_TYPE(BACKGROUND, 0)
+DECLARE_DISPLAY_ITEM_TYPE(THEMED_BACKGROUND, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(BACKGROUND_COLOR, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(BLEND_CONTAINER, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(BLEND_MODE, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(BORDER, 0)
+DECLARE_DISPLAY_ITEM_TYPE(BOX_SHADOW_OUTER, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(BOX_SHADOW_INNER, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(BULLET, 0)
+DECLARE_DISPLAY_ITEM_TYPE(BUTTON_BORDER_BACKGROUND, 0)
+DECLARE_DISPLAY_ITEM_TYPE(BUTTON_BOX_SHADOW_OUTER, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(BUTTON_FOREGROUND, 0)
+DECLARE_DISPLAY_ITEM_TYPE(CANVAS, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(CANVAS_BACKGROUND_COLOR, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(CANVAS_THEMED_BACKGROUND, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(CANVAS_BACKGROUND_IMAGE, 0)
+DECLARE_DISPLAY_ITEM_TYPE(CANVAS_FOCUS, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(CARET, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(CHECKED_CHECKBOX, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(CHECKED_RADIOBUTTON, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(CLEAR_BACKGROUND, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(COLUMN_RULE, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(COMBOBOX_FOCUS, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(EVENT_RECEIVER, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(LAYER_EVENT_REGIONS, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(FIELDSET_BORDER_BACKGROUND, 0)
+DECLARE_DISPLAY_ITEM_TYPE(FIXED_POSITION, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(STICKY_POSITION, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(FRAMESET_BORDER, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(FRAMESET_BLANK, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(HEADER_FOOTER, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(IMAGE, 0)
+DECLARE_DISPLAY_ITEM_TYPE(LIST_FOCUS, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(OPACITY, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(OPTION_EVENT_GRABBER, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(OUTLINE, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(OWN_LAYER, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(PLUGIN, 0)
+DECLARE_DISPLAY_ITEM_TYPE(PLUGIN_READBACK, 0)
+DECLARE_DISPLAY_ITEM_TYPE(PRINT_PLUGIN, 0)
+DECLARE_DISPLAY_ITEM_TYPE(RANGE_FOCUS_RING, 0)
+DECLARE_DISPLAY_ITEM_TYPE(REMOTE, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(RESOLUTION, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(SCROLL_INFO_LAYER, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(SELECTION_OVERLAY, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(SOLID_COLOR, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(SOLID_COLOR_REGION, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(SUBDOCUMENT, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(MASK, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(FILTER, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(SVG_OUTER_SVG, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(SVG_GEOMETRY, 0)
+DECLARE_DISPLAY_ITEM_TYPE(SVG_TEXT, 0)
+DECLARE_DISPLAY_ITEM_TYPE(TABLE_CELL_BACKGROUND, 0)
+DECLARE_DISPLAY_ITEM_TYPE(TABLE_CELL_SELECTION, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(TABLE_BORDER_COLLAPSE, 0)
+DECLARE_DISPLAY_ITEM_TYPE(TABLE_BACKGROUND_COLOR, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(TABLE_BACKGROUND_IMAGE, 0)
+DECLARE_DISPLAY_ITEM_TYPE(TABLE_FIXED_POSITION, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(TEXT, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(TEXT_OVERFLOW, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(TRANSFORM,TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(PERSPECTIVE,TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(VIDEO, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(WRAP_LIST, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(ZOOM, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(GENERIC, TYPE_RENDERS_NO_IMAGES)
 
 #if defined(MOZ_REFLOW_PERF_DSP) && defined(MOZ_REFLOW_PERF)
-DECLARE_DISPLAY_ITEM_TYPE(REFLOW_COUNT)
+DECLARE_DISPLAY_ITEM_TYPE(REFLOW_COUNT, TYPE_RENDERS_NO_IMAGES)
 #endif
 
 #ifdef MOZ_XUL
-DECLARE_DISPLAY_ITEM_TYPE(XUL_EVENT_REDIRECTOR)
-DECLARE_DISPLAY_ITEM_TYPE(XUL_GROUP_BACKGROUND)
-DECLARE_DISPLAY_ITEM_TYPE(XUL_IMAGE)
-DECLARE_DISPLAY_ITEM_TYPE(XUL_TEXT_BOX)
-DECLARE_DISPLAY_ITEM_TYPE(XUL_TREE_BODY)
-DECLARE_DISPLAY_ITEM_TYPE(XUL_TREE_COL_SPLITTER_TARGET)
+DECLARE_DISPLAY_ITEM_TYPE(XUL_EVENT_REDIRECTOR, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(XUL_GROUP_BACKGROUND, 0)
+DECLARE_DISPLAY_ITEM_TYPE(XUL_IMAGE, 0)
+DECLARE_DISPLAY_ITEM_TYPE(XUL_TEXT_BOX, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(XUL_TREE_BODY, 0)
+DECLARE_DISPLAY_ITEM_TYPE(XUL_TREE_COL_SPLITTER_TARGET, TYPE_RENDERS_NO_IMAGES)
 #ifdef DEBUG_LAYOUT
-DECLARE_DISPLAY_ITEM_TYPE(XUL_DEBUG)
+DECLARE_DISPLAY_ITEM_TYPE(XUL_DEBUG, TYPE_RENDERS_NO_IMAGES)
 #endif
 #endif
 
-DECLARE_DISPLAY_ITEM_TYPE(MATHML_BAR)
-DECLARE_DISPLAY_ITEM_TYPE(MATHML_CHAR_FOREGROUND)
-DECLARE_DISPLAY_ITEM_TYPE(MATHML_ERROR)
-DECLARE_DISPLAY_ITEM_TYPE(MATHML_MENCLOSE_NOTATION)
-DECLARE_DISPLAY_ITEM_TYPE(MATHML_SELECTION_RECT)
-DECLARE_DISPLAY_ITEM_TYPE(MATHML_SLASH)
+DECLARE_DISPLAY_ITEM_TYPE(MATHML_BAR, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(MATHML_CHAR_FOREGROUND, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(MATHML_ERROR, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(MATHML_MENCLOSE_NOTATION, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(MATHML_SELECTION_RECT, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(MATHML_SLASH, TYPE_RENDERS_NO_IMAGES)
 #ifdef DEBUG
-DECLARE_DISPLAY_ITEM_TYPE(MATHML_BOUNDING_METRICS)
-DECLARE_DISPLAY_ITEM_TYPE(MATHML_CHAR_DEBUG)
+DECLARE_DISPLAY_ITEM_TYPE(MATHML_BOUNDING_METRICS, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(MATHML_CHAR_DEBUG, TYPE_RENDERS_NO_IMAGES)
 
-DECLARE_DISPLAY_ITEM_TYPE(DEBUG_BORDER)
-DECLARE_DISPLAY_ITEM_TYPE(DEBUG_IMAGE_MAP)
-DECLARE_DISPLAY_ITEM_TYPE(DEBUG_PLACEHOLDER)
-DECLARE_DISPLAY_ITEM_TYPE(EVENT_TARGET_BORDER)
+DECLARE_DISPLAY_ITEM_TYPE(DEBUG_BORDER, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(DEBUG_IMAGE_MAP, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(DEBUG_PLACEHOLDER, TYPE_RENDERS_NO_IMAGES)
+DECLARE_DISPLAY_ITEM_TYPE(EVENT_TARGET_BORDER, TYPE_RENDERS_NO_IMAGES)
 #endif
--- a/layout/reftests/css-break/reftest.list
+++ b/layout/reftests/css-break/reftest.list
@@ -1,13 +1,13 @@
 default-preferences pref(layout.css.box-decoration-break.enabled,true)
 
 == box-decoration-break-1.html box-decoration-break-1-ref.html
 fuzzy(1,20) fuzzy-if(skiaContent,1,700) fuzzy-if(webrender,4-4,36-36) == box-decoration-break-with-inset-box-shadow-1.html box-decoration-break-with-inset-box-shadow-1-ref.html
-fuzzy(16,460) fuzzy-if(skiaContent,57,374) fuzzy-if(Android,57,1330) fuzzy-if(styloVsGecko,2,1410) == box-decoration-break-with-outset-box-shadow-1.html box-decoration-break-with-outset-box-shadow-1-ref.html # Bug 1386543
+fuzzy(45,460) fuzzy-if(skiaContent,57,374) fuzzy-if(Android,57,1330) fuzzy-if(styloVsGecko,2,1410) == box-decoration-break-with-outset-box-shadow-1.html box-decoration-break-with-outset-box-shadow-1-ref.html # Bug 1386543
 random-if(!gtkWidget) HTTP(..) == box-decoration-break-border-image.html box-decoration-break-border-image-ref.html
 == box-decoration-break-block-border-padding.html box-decoration-break-block-border-padding-ref.html
 == box-decoration-break-block-margin.html box-decoration-break-block-margin-ref.html
 fuzzy-if(!Android,1,62) fuzzy-if(Android,8,6627) == box-decoration-break-first-letter.html box-decoration-break-first-letter-ref.html #Bug 1313773
 == box-decoration-break-with-bidi.html box-decoration-break-with-bidi-ref.html
 == box-decoration-break-bug-1235152.html box-decoration-break-bug-1235152-ref.html
 == box-decoration-break-bug-1249913.html box-decoration-break-bug-1249913-ref.html
 == vertical-wm-001.html vertical-wm-001-ref.html
--- a/mobile/android/base/java/org/mozilla/gecko/customtabs/ActionBarPresenter.java
+++ b/mobile/android/base/java/org/mozilla/gecko/customtabs/ActionBarPresenter.java
@@ -203,23 +203,23 @@ public class ActionBarPresenter {
      * @param security A SecurityInformation object giving the current security information
      */
     @UiThread
     private void updateCustomView(final String title, final String url, final SecurityInformation security) {
         if (security == null) {
             mIconView.setVisibility(View.INVISIBLE);
         } else {
             SecurityModeUtil.IconType icon;
-            if ("unknown".equals(security.securityMode)) {
+            if (SecurityInformation.SECURITY_MODE_UNKNOWN == security.securityMode) {
                 icon = SecurityModeUtil.IconType.UNKNOWN;
             } else {
                 icon = SecurityModeUtil.IconType.LOCK_SECURE;
             }
 
-            if ("loaded".equals(security.mixedModePassive)) {
+            if (SecurityInformation.CONTENT_LOADED == security.mixedModePassive) {
                 icon = SecurityModeUtil.IconType.WARNING;
             }
 
             mIconView.setVisibility(View.VISIBLE);
             mIconView.setImageLevel(SecurityModeUtil.getImageLevel(icon));
             mIdentityPopup.setSecurityInformation(security);
 
             if (icon == SecurityModeUtil.IconType.LOCK_SECURE) {
--- a/mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsSecurityPopup.java
+++ b/mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsSecurityPopup.java
@@ -100,18 +100,18 @@ public class CustomTabsSecurityPopup ext
         mVerifier = (TextView) mIdentityKnownContainer.findViewById(R.id.verifier);
     }
 
     private void updateSecurityInformation(final SecurityInformation security) {
         if (!mInflated) {
             init();
         }
 
-        final boolean isIdentityKnown = ("identified".equals(security.securityMode) ||
-                                         "verified".equals(security.securityMode));
+        final boolean isIdentityKnown = (SecurityInformation.SECURITY_MODE_IDENTIFIED == security.securityMode ||
+                                         SecurityInformation.SECURITY_MODE_VERIFIED == security.securityMode);
         updateConnectionState(security);
         toggleIdentityKnownContainerVisibility(isIdentityKnown);
 
         if (isIdentityKnown) {
             updateIdentityInformation(security);
         }
     }
 
@@ -127,61 +127,60 @@ public class CustomTabsSecurityPopup ext
      * a) Connection encryption
      * b) Mixed Content state (Active/Display Mixed content, loaded, blocked, none, etc)
      * and update the icons and strings to inform the user of that state.
      *
      * @param security SecurityInformation about the connection.
      */
     private void updateConnectionState(final SecurityInformation security) {
         if (!security.isSecure) {
-            if ("loaded".equals(security.mixedModeActive)) {
+            if (SecurityInformation.CONTENT_LOADED == security.mixedModeActive) {
                 // Active Mixed Content loaded because user has disabled blocking.
                 mIcon.setImageResource(R.drawable.ic_lock_disabled);
                 clearSecurityStateIcon();
                 mMixedContentActivity.setVisibility(View.VISIBLE);
                 mMixedContentActivity.setText(R.string.mixed_content_protection_disabled);
-            } else if ("loaded".equals(security.mixedModePassive)) {
+            } else if (SecurityInformation.CONTENT_LOADED == security.mixedModePassive) {
                 // Passive Mixed Content loaded.
                 mIcon.setImageResource(R.drawable.ic_lock_inactive);
                 setSecurityStateIcon(R.drawable.ic_warning_major, 1);
                 mMixedContentActivity.setVisibility(View.VISIBLE);
-                if ("blocked".equals(security.mixedModeActive)) {
+                if (SecurityInformation.CONTENT_BLOCKED == security.mixedModeActive) {
                     mMixedContentActivity.setText(R.string.mixed_content_blocked_some);
                 } else {
                     mMixedContentActivity.setText(R.string.mixed_content_display_loaded);
                 }
             } else {
                 // Unencrypted connection with no mixed content.
                 mIcon.setImageResource(R.drawable.globe_light);
                 clearSecurityStateIcon();
 
                 mMixedContentActivity.setVisibility(View.GONE);
             }
 
             mSecurityState.setText(R.string.identity_connection_insecure);
             mSecurityState.setTextColor(ContextCompat.getColor(mContext, R.color.placeholder_active_grey));
 
         } else if (security.isException) {
-
             mIcon.setImageResource(R.drawable.ic_lock_inactive);
             setSecurityStateIcon(R.drawable.ic_warning_major, 1);
             mSecurityState.setText(R.string.identity_connection_insecure);
             mSecurityState.setTextColor(ContextCompat.getColor(mContext, R.color.placeholder_active_grey));
 
         } else {
             // Connection is secure.
             mIcon.setImageResource(R.drawable.ic_lock);
 
             setSecurityStateIcon(R.drawable.img_check, 2);
             mSecurityState.setTextColor(ContextCompat.getColor(mContext, R.color.affirmative_green));
             mSecurityState.setText(R.string.identity_connection_secure);
 
             // Mixed content has been blocked, if present.
-            if ("blocked".equals(security.mixedModeActive) ||
-                "blocked".equals(security.mixedModePassive)) {
+            if (SecurityInformation.CONTENT_BLOCKED == security.mixedModeActive ||
+                SecurityInformation.CONTENT_BLOCKED == security.mixedModePassive) {
                 mMixedContentActivity.setVisibility(View.VISIBLE);
                 mMixedContentActivity.setText(R.string.mixed_content_blocked_all);
             } else {
                 mMixedContentActivity.setVisibility(View.GONE);
             }
         }
     }
 
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoView.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoView.java
@@ -1230,16 +1230,23 @@ public class GeckoView extends LayerView
         return mEventDispatcher;
     }
 
     public interface ProgressListener {
         /**
          * Class representing security information for a site.
          */
         public class SecurityInformation {
+            public static final int SECURITY_MODE_UNKNOWN = 0;
+            public static final int SECURITY_MODE_IDENTIFIED = 1;
+            public static final int SECURITY_MODE_VERIFIED = 2;
+
+            public static final int CONTENT_UNKNOWN = 0;
+            public static final int CONTENT_BLOCKED = 1;
+            public static final int CONTENT_LOADED = 2;
             /**
              * Indicates whether or not the site is secure.
              */
             public final boolean isSecure;
             /**
              * Indicates whether or not the site is a security exception.
              */
             public final boolean isException;
@@ -1263,45 +1270,45 @@ public class GeckoView extends LayerView
              * Contains the common name of the issuing authority.
              */
             public final String issuerCommonName;
             /**
              * Contains the full/proper name of the issuing authority.
              */
             public final String issuerOrganization;
             /**
-             * Indicates the security level of the site; possible values are "unknown",
-             * "identified", and "verified". "identified" indicates domain validation only,
-             * while "verified" indicates extended validation.
+             * Indicates the security level of the site; possible values are SECURITY_MODE_UNKNOWN,
+             * SECURITY_MODE_IDENTIFIED, and SECURITY_MODE_VERIFIED. SECURITY_MODE_IDENTIFIED 
+             * indicates domain validation only, while SECURITY_MODE_VERIFIED indicates extended validation.
              */
-            public final String securityMode;
+            public final int securityMode;
             /**
              * Indicates the presence of passive mixed content; possible values are
-             * "unknown", "blocked", and "loaded".
+             * CONTENT_UNKNOWN, CONTENT_BLOCKED, and CONTENT_LOADED.
              */
-            public final String mixedModePassive;
+            public final int mixedModePassive;
             /**
              * Indicates the presence of active mixed content; possible values are
-             * "unknown", "blocked", and "loaded".
+             * CONTENT_UNKNOWN, CONTENT_BLOCKED, and CONTENT_LOADED.
              */
-            public final String mixedModeActive;
+            public final int mixedModeActive;
             /**
              * Indicates the status of tracking protection; possible values are
-             * "unknown", "blocked", and "loaded".
+             * CONTENT_UNKNOWN, CONTENT_BLOCKED, and CONTENT_LOADED.
              */
-            public final String trackingMode;
+            public final int trackingMode;
 
             /* package */ SecurityInformation(GeckoBundle identityData) {
                 final GeckoBundle mode = identityData.getBundle("mode");
 
-                mixedModePassive = mode.getString("mixed_display");
-                mixedModeActive = mode.getString("mixed_active");
-                trackingMode = mode.getString("tracking");
+                mixedModePassive = mode.getInt("mixed_display");
+                mixedModeActive = mode.getInt("mixed_active");
+                trackingMode = mode.getInt("tracking");
 
-                securityMode = mode.getString("identity");
+                securityMode = mode.getInt("identity");
 
                 isSecure = identityData.getBoolean("secure");
                 isException = identityData.getBoolean("securityException");
                 origin = identityData.getString("origin");
                 host = identityData.getString("host");
                 organization = identityData.getString("organization");
                 subjectName = identityData.getString("subjectName");
                 issuerCommonName = identityData.getString("issuerCommonName");
--- a/mobile/android/modules/geckoview/GeckoViewProgress.jsm
+++ b/mobile/android/modules/geckoview/GeckoViewProgress.jsm
@@ -19,48 +19,49 @@ XPCOMUtils.defineLazyGetter(this, "dump"
     Cu.import("resource://gre/modules/AndroidLog.jsm",
               {}).AndroidLog.d.bind(null, "ViewProgress"));
 
 function debug(aMsg) {
   // dump(aMsg);
 }
 
 var IdentityHandler = {
+  // The definitions below should be kept in sync with those in GeckoView.ProgressListener.SecurityInformation
   // No trusted identity information. No site identity icon is shown.
-  IDENTITY_MODE_UNKNOWN: "unknown",
+  IDENTITY_MODE_UNKNOWN: 0,
 
   // Domain-Validation SSL CA-signed domain verification (DV).
-  IDENTITY_MODE_IDENTIFIED: "identified",
+  IDENTITY_MODE_IDENTIFIED: 1,
 
   // Extended-Validation SSL CA-signed identity information (EV). A more rigorous validation process.
-  IDENTITY_MODE_VERIFIED: "verified",
+  IDENTITY_MODE_VERIFIED: 2,
 
   // The following mixed content modes are only used if "security.mixed_content.block_active_content"
   // is enabled. Our Java frontend coalesces them into one indicator.
 
   // No mixed content information. No mixed content icon is shown.
-  MIXED_MODE_UNKNOWN: "unknown",
+  MIXED_MODE_UNKNOWN: 0,
 
   // Blocked active mixed content.
-  MIXED_MODE_CONTENT_BLOCKED: "blocked",
+  MIXED_MODE_CONTENT_BLOCKED: 1,
 
   // Loaded active mixed content.
-  MIXED_MODE_CONTENT_LOADED: "loaded",
+  MIXED_MODE_CONTENT_LOADED: 2,
 
   // The following tracking content modes are only used if tracking protection
   // is enabled. Our Java frontend coalesces them into one indicator.
 
   // No tracking content information. No tracking content icon is shown.
-  TRACKING_MODE_UNKNOWN: "unknown",
+  TRACKING_MODE_UNKNOWN: 0,
 
   // Blocked active tracking content. Shield icon is shown, with a popup option to load content.
-  TRACKING_MODE_CONTENT_BLOCKED: "blocked",
+  TRACKING_MODE_CONTENT_BLOCKED: 1,
 
   // Loaded active tracking content. Yellow triangle icon is shown.
-  TRACKING_MODE_CONTENT_LOADED: "loaded",
+  TRACKING_MODE_CONTENT_LOADED: 2,
 
   _useTrackingProtection: false,
   _usePrivateMode: false,
 
   setUseTrackingProtection: function(aUse) {
     this._useTrackingProtection = aUse;
   },
 
--- a/testing/mochitest/browser-test.js
+++ b/testing/mochitest/browser-test.js
@@ -207,17 +207,17 @@ Tester.prototype = {
   lastStartTime: null,
   lastAssertionCount: 0,
   failuresFromInitialWindowState: 0,
 
   get currentTest() {
     return this.tests[this.currentTestIndex];
   },
   get done() {
-    return this.currentTestIndex == this.tests.length - 1;
+    return (this.currentTestIndex == this.tests.length - 1) && (this.repeat <= 0);
   },
 
   start: function Tester_start() {
     TabDestroyObserver.init();
 
     //if testOnLoad was not called, then gConfig is not defined
     if (!gConfig)
       gConfig = readConfig();
@@ -331,50 +331,44 @@ Tester.prototype = {
   finish: function Tester_finish(aSkipSummary) {
     var passCount = this.tests.reduce((a, f) => a + f.passCount, 0);
     var failCount = this.tests.reduce((a, f) => a + f.failCount, 0);
     var todoCount = this.tests.reduce((a, f) => a + f.todoCount, 0);
 
     // Include failures from window state checking prior to running the first test
     failCount += this.failuresFromInitialWindowState;
 
-    if (this.repeat > 0) {
-      --this.repeat;
-      this.currentTestIndex = -1;
-      this.nextTest();
-    } else {
-      TabDestroyObserver.destroy();
-      Services.console.unregisterListener(this);
+    TabDestroyObserver.destroy();
+    Services.console.unregisterListener(this);
+
+    // It's important to terminate the module to avoid crashes on shutdown.
+    this.PromiseTestUtils.uninit();
 
-      // It's important to terminate the module to avoid crashes on shutdown.
-      this.PromiseTestUtils.uninit();
+    // In the main process, we print the ShutdownLeaksCollector message here.
+    let pid = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).processID;
+    dump("Completed ShutdownLeaks collections in process " + pid + "\n");
 
-      // In the main process, we print the ShutdownLeaksCollector message here.
-      let pid = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).processID;
-      dump("Completed ShutdownLeaks collections in process " + pid + "\n");
-
-      this.structuredLogger.info("TEST-START | Shutdown");
+    this.structuredLogger.info("TEST-START | Shutdown");
 
-      if (this.tests.length) {
-        let e10sMode = gMultiProcessBrowser ? "e10s" : "non-e10s";
-        this.structuredLogger.info("Browser Chrome Test Summary");
-        this.structuredLogger.info("Passed:  " + passCount);
-        this.structuredLogger.info("Failed:  " + failCount);
-        this.structuredLogger.info("Todo:    " + todoCount);
-        this.structuredLogger.info("Mode:    " + e10sMode);
-      } else {
-        this.structuredLogger.error("browser-test.js | No tests to run. Did you pass invalid test_paths?");
-      }
-      this.structuredLogger.info("*** End BrowserChrome Test Results ***");
+    if (this.tests.length) {
+      let e10sMode = gMultiProcessBrowser ? "e10s" : "non-e10s";
+      this.structuredLogger.info("Browser Chrome Test Summary");
+      this.structuredLogger.info("Passed:  " + passCount);
+      this.structuredLogger.info("Failed:  " + failCount);
+      this.structuredLogger.info("Todo:    " + todoCount);
+      this.structuredLogger.info("Mode:    " + e10sMode);
+    } else {
+      this.structuredLogger.error("browser-test.js | No tests to run. Did you pass invalid test_paths?");
+    }
+    this.structuredLogger.info("*** End BrowserChrome Test Results ***");
 
-      // Tests complete, notify the callback and return
-      this.callback(this.tests);
-      this.callback = null;
-      this.tests = null;
-    }
+    // Tests complete, notify the callback and return
+    this.callback(this.tests);
+    this.callback = null;
+    this.tests = null;
   },
 
   haltTests: function Tester_haltTests() {
     // Do not run any further tests
     this.currentTestIndex = this.tests.length - 1;
     this.repeat = 0;
   },
 
@@ -685,18 +679,28 @@ Tester.prototype = {
               });
             }, 1000);
           });
         });
 
         return;
       }
 
-      this.currentTestIndex++;
-      this.execTest();
+      if (this.repeat > 0) {
+        --this.repeat;
+        if (this.currentTestIndex < 0) {
+          this.currentTestIndex = 0;
+        }
+        this.execTest();
+      } else {
+        this.currentTestIndex++;
+        if (gConfig.repeat)
+          this.repeat = gConfig.repeat;
+        this.execTest();
+      }
     });
   }),
 
   execTest: function Tester_execTest() {
     this.structuredLogger.testStart(this.currentTest.path);
 
     this.SimpleTest.reset();
 
--- a/toolkit/components/crashes/CrashService.js
+++ b/toolkit/components/crashes/CrashService.js
@@ -5,19 +5,26 @@
 "use strict";
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
 Cu.import("resource://gre/modules/AppConstants.jsm", this);
 Cu.import("resource://gre/modules/AsyncShutdown.jsm", this);
 Cu.import("resource://gre/modules/KeyValueParser.jsm");
 Cu.import("resource://gre/modules/osfile.jsm", this);
+Cu.import("resource://gre/modules/PromiseUtils.jsm", this);
 Cu.import("resource://gre/modules/Services.jsm", this);
 Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
 
+// Set to true if the application is quitting
+var gQuitting = false;
+
+// Tracks all the running instances of the minidump-analyzer
+var gRunningProcesses = new Set();
+
 /**
  * Run the minidump analyzer tool to gather stack traces from the minidump. The
  * stack traces will be stored in the .extra file under the StackTraces= entry.
  *
  * @param minidumpPath {string} The path to the minidump file
  *
  * @returns {Promise} A promise that gets resolved once minidump analysis has
  *          finished.
@@ -26,38 +33,41 @@ function runMinidumpAnalyzer(minidumpPat
   return new Promise((resolve, reject) => {
     try {
       const binSuffix = AppConstants.platform === "win" ? ".exe" : "";
       const exeName = "minidump-analyzer" + binSuffix;
 
       let exe = Services.dirsvc.get("GreBinD", Ci.nsIFile);
 
       if (AppConstants.platform === "macosx") {
-          exe.append("crashreporter.app");
-          exe.append("Contents");
-          exe.append("MacOS");
+        exe.append("crashreporter.app");
+        exe.append("Contents");
+        exe.append("MacOS");
       }
 
       exe.append(exeName);
 
       let args = [ minidumpPath ];
       let process = Cc["@mozilla.org/process/util;1"]
                       .createInstance(Ci.nsIProcess);
       process.init(exe);
       process.startHidden = true;
       process.runAsync(args, args.length, (subject, topic, data) => {
         switch (topic) {
           case "process-finished":
+            gRunningProcesses.delete(process);
             resolve();
             break;
           default:
             reject(new Error("Unexpected topic received " + topic));
             break;
         }
       });
+
+      gRunningProcesses.add(process);
     } catch (e) {
       Cu.reportError(e);
     }
   });
 }
 
 /**
  * Computes the SHA256 hash of a minidump file
@@ -115,17 +125,19 @@ function processExtraFile(extraPath) {
   })();
 }
 
 /**
  * This component makes crash data available throughout the application.
  *
  * It is a service because some background activity will eventually occur.
  */
-this.CrashService = function() {};
+this.CrashService = function() {
+  Services.obs.addObserver(this, "quit-application");
+};
 
 CrashService.prototype = Object.freeze({
   classID: Components.ID("{92668367-1b17-4190-86b2-1061b2179744}"),
   QueryInterface: XPCOMUtils.generateQI([
     Ci.nsICrashService,
     Ci.nsIObserver,
   ]),
 
@@ -163,17 +175,22 @@ CrashService.prototype = Object.freeze({
 
     let cr = Cc["@mozilla.org/toolkit/crash-reporter;1"]
                .getService(Components.interfaces.nsICrashReporter);
     let minidumpPath = cr.getMinidumpForID(id).path;
     let extraPath = cr.getExtraFileForID(id).path;
     let metadata = {};
     let hash = null;
 
-    await runMinidumpAnalyzer(minidumpPath);
+    if (!gQuitting) {
+      // Minidump analysis can take a long time, don't start it if the browser
+      // is already quitting.
+      await runMinidumpAnalyzer(minidumpPath);
+    }
+
     metadata = await processExtraFile(extraPath);
     hash = await computeMinidumpHash(minidumpPath);
 
     if (hash) {
       metadata.MinidumpSha256Hash = hash;
     }
 
     let blocker = Services.crashmanager.addCrash(processType, crashType, id,
@@ -189,13 +206,20 @@ CrashService.prototype = Object.freeze({
   },
 
   observe(subject, topic, data) {
     switch (topic) {
       case "profile-after-change":
         // Side-effect is the singleton is instantiated.
         Services.crashmanager;
         break;
+      case "quit-application":
+        gQuitting = true;
+        gRunningProcesses.forEach((process) => {
+          process.kill();
+          Services.obs.notifyObservers(null, "test-minidump-analyzer-killed");
+        });
+        break;
     }
   },
 });
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([CrashService]);
--- a/toolkit/components/crashes/tests/xpcshell/test_crash_service.js
+++ b/toolkit/components/crashes/tests/xpcshell/test_crash_service.js
@@ -2,16 +2,17 @@
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 var {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
 Cu.import("resource://gre/modules/osfile.jsm", this);
 Cu.import("resource://gre/modules/Services.jsm", this);
+Cu.import("resource://gre/modules/Timer.jsm");
 Cu.import("resource://testing-common/AppData.jsm", this);
 Cu.import("resource://testing-common/CrashManagerTest.jsm", this);
 var bsp = Cu.import("resource://gre/modules/CrashManager.jsm", {});
 
 add_task(async function test_instantiation() {
   Assert.ok(!bsp.gCrashManager, "CrashManager global instance not initially defined.");
 
   do_get_profile();
@@ -23,33 +24,50 @@ add_task(async function test_instantiati
     .observe(null, "profile-after-change", null);
 
   Assert.ok(bsp.gCrashManager, "Profile creation makes it available.");
   Assert.ok(Services.crashmanager, "CrashManager available via Services.");
   Assert.strictEqual(bsp.gCrashManager, Services.crashmanager,
                      "The objects are the same.");
 });
 
-add_task(async function test_addCrash() {
-  const crashId = "56cd87bc-bb26-339b-3a8e-f00c0f11380e";
+var gMinidumpDir = do_get_tempdir();
+var gCrashReporter = Cc["@mozilla.org/toolkit/crash-reporter;1"]
+                       .getService(Ci.nsICrashReporter);
+
+// Ensure that the nsICrashReporter methods can find the dump
+gCrashReporter.minidumpPath = gMinidumpDir;
 
+var gDumpFile;
+var gExtraFile;
+
+// Sets up a fake crash dump and sets up the crashreporter so that it will be
+// able to find it.
+async function setup(crashId) {
   let cwd = await OS.File.getCurrentDirectory();
   let minidump = OS.Path.join(cwd, "crash.dmp");
   let extra = OS.Path.join(cwd, "crash.extra");
-  let dir = do_get_tempdir();
 
   // Make a copy of the files because the .extra file will be modified
-  await OS.File.copy(minidump, OS.Path.join(dir.path, crashId + ".dmp"));
-  await OS.File.copy(extra, OS.Path.join(dir.path, crashId + ".extra"));
+  gDumpFile = OS.Path.join(gMinidumpDir.path, crashId + ".dmp");
+  await OS.File.copy(minidump, gDumpFile);
+  gExtraFile = OS.Path.join(gMinidumpDir.path, crashId + ".extra");
+  await OS.File.copy(extra, gExtraFile);
+
+}
 
-  // Ensure that the nsICrashReporter methods can find the dump
-  let crashReporter =
-      Components.classes["@mozilla.org/toolkit/crash-reporter;1"]
-                .getService(Components.interfaces.nsICrashReporter);
-  crashReporter.minidumpPath = dir;
+// Cleans up the fake crash dump and resets the minidump path
+async function teardown() {
+  await OS.File.remove(gDumpFile);
+  await OS.File.remove(gExtraFile);
+}
+
+add_task(async function test_addCrash() {
+  const crashId = "56cd87bc-bb26-339b-3a8e-f00c0f11380e";
+  await setup(crashId);
 
   let cs = Cc["@mozilla.org/crashservice;1"].getService(Ci.nsICrashService);
   await cs.addCrash(Ci.nsICrashService.PROCESS_TYPE_CONTENT,
                     Ci.nsICrashService.CRASH_TYPE_CRASH, crashId);
   let crashes = await Services.crashmanager.getCrashes();
   let crash = crashes.find(c => { return c.id === crashId; });
   Assert.ok(crash, "Crash " + crashId + " has been stored successfully.");
   Assert.equal(crash.metadata.ProcessType, "content");
@@ -67,11 +85,62 @@ add_task(async function test_addCrash() 
               "The thread list is populated.");
 
     let frames = stackTraces.threads[0].frames;
     Assert.ok(frames && (frames.length > 0), "The stack trace is present.\n");
   } catch (e) {
     Assert.ok(false, "StackTraces does not contain valid JSON.");
   }
 
-  // Remove the minidumps to prevent the test harness from thinking we crashed
-  await OS.File.removeDir(dir.path);
+  await teardown();
 });
+
+add_task(async function test_addCrash_quitting() {
+  const firstCrashId = "0e578a74-a887-48cb-b270-d4775d01e715";
+  const secondCrashId = "208379e5-1979-430d-a066-f6e57a8130ce";
+
+  await setup(firstCrashId);
+
+  let minidumpAnalyzerKilledPromise = new Promise((resolve, reject) => {
+    Services.obs.addObserver((subject, topic, data) => {
+      if (topic === "test-minidump-analyzer-killed") {
+        resolve();
+      }
+
+      reject();
+    }, "test-minidump-analyzer-killed");