Merge f-t to m-c, a=merge
authorPhil Ringnalda <philringnalda@gmail.com>
Fri, 30 Sep 2016 23:25:36 -0700
changeset 316119 87cd291d2db621da6b3eb1057027cc0725b6eb1d
parent 316107 fcc62bbf09eecabf27c8d198d5d3719e16b296ea (current diff)
parent 316118 d69d58af9bea7a2781304d3ee3ba2122b2c07abf (diff)
child 316120 bd880243ff4ceaf6f9527205f47107ccf55e8e87
child 316124 f6c57c2fba75b0d55f28b2460d9587a0d3796cc5
child 316131 aa4fe3cf49e0b60642a23cc2d5bcf9e50d204d9a
push id82344
push userphilringnalda@gmail.com
push dateSat, 01 Oct 2016 06:27:41 +0000
treeherdermozilla-inbound@87cd291d2db6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone52.0a1
first release with
nightly linux32
87cd291d2db6 / 52.0a1 / 20161001030430 / files
nightly linux64
87cd291d2db6 / 52.0a1 / 20161001030430 / files
nightly mac
87cd291d2db6 / 52.0a1 / 20161001030430 / files
nightly win32
87cd291d2db6 / 52.0a1 / 20161001030430 / files
nightly win64
87cd291d2db6 / 52.0a1 / 20161001030430 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge f-t to m-c, a=merge
devtools/client/debugger/new/test/mochitest/examples/code-exceptions.js
devtools/client/debugger/new/test/mochitest/examples/code-long.js
devtools/client/debugger/new/test/mochitest/examples/code-script-switching-01.js
devtools/client/debugger/new/test/mochitest/examples/code-script-switching-02.js
devtools/client/debugger/new/test/mochitest/examples/code-simple1.js
devtools/client/debugger/new/test/mochitest/examples/code-simple2.js
--- a/browser/extensions/pdfjs/README.mozilla
+++ b/browser/extensions/pdfjs/README.mozilla
@@ -1,3 +1,3 @@
 This is the pdf.js project output, https://github.com/mozilla/pdf.js
 
-Current extension version is: 1.5.476
+Current extension version is: 1.5.498
--- a/browser/extensions/pdfjs/content/build/pdf.js
+++ b/browser/extensions/pdfjs/content/build/pdf.js
@@ -23,18 +23,18 @@ define('pdfjs-dist/build/pdf', ['exports
     factory(exports);
   } else {
 factory((root.pdfjsDistBuildPdf = {}));
   }
 }(this, function (exports) {
   // Use strict in our context only - users might not want it
   'use strict';
 
-var pdfjsVersion = '1.5.476';
-var pdfjsBuild = 'c0e82db';
+var pdfjsVersion = '1.5.498';
+var pdfjsBuild = '1564dc3';
 
   var pdfjsFilePath =
     typeof document !== 'undefined' && document.currentScript ?
       document.currentScript.src : null;
 
   var pdfjsLibs = {};
 
   (function pdfjsWrapper() {
@@ -110,35 +110,35 @@ var AnnotationFlag = {
   NOVIEW: 0x20,
   READONLY: 0x40,
   LOCKED: 0x80,
   TOGGLENOVIEW: 0x100,
   LOCKEDCONTENTS: 0x200
 };
 
 var AnnotationFieldFlag = {
-  READONLY: 1,
-  REQUIRED: 2,
-  NOEXPORT: 3,
-  MULTILINE: 13,
-  PASSWORD: 14,
-  NOTOGGLETOOFF: 15,
-  RADIO: 16,
-  PUSHBUTTON: 17,
-  COMBO: 18,
-  EDIT: 19,
-  SORT: 20,
-  FILESELECT: 21,
-  MULTISELECT: 22,
-  DONOTSPELLCHECK: 23,
-  DONOTSCROLL: 24,
-  COMB: 25,
-  RICHTEXT: 26,
-  RADIOSINUNISON: 26,
-  COMMITONSELCHANGE: 27,
+  READONLY: 0x0000001,
+  REQUIRED: 0x0000002,
+  NOEXPORT: 0x0000004,
+  MULTILINE: 0x0001000,
+  PASSWORD: 0x0002000,
+  NOTOGGLETOOFF: 0x0004000,
+  RADIO: 0x0008000,
+  PUSHBUTTON: 0x0010000,
+  COMBO: 0x0020000,
+  EDIT: 0x0040000,
+  SORT: 0x0080000,
+  FILESELECT: 0x0100000,
+  MULTISELECT: 0x0200000,
+  DONOTSPELLCHECK: 0x0400000,
+  DONOTSCROLL: 0x0800000,
+  COMB: 0x1000000,
+  RICHTEXT: 0x2000000,
+  RADIOSINUNISON: 0x2000000,
+  COMMITONSELCHANGE: 0x4000000,
 };
 
 var AnnotationBorderStyleType = {
   SOLID: 1,
   DASHED: 2,
   BEVELED: 3,
   INSET: 4,
   UNDERLINE: 5
@@ -2360,29 +2360,41 @@ var TextWidgetAnnotationElement = (
      * @memberof TextWidgetAnnotationElement
      * @returns {HTMLSectionElement}
      */
     render: function TextWidgetAnnotationElement_render() {
       this.container.className = 'textWidgetAnnotation';
 
       var element = null;
       if (this.renderInteractiveForms) {
+        // NOTE: We cannot set the values using `element.value` below, since it
+        //       prevents the AnnotationLayer rasterizer in `test/driver.js`
+        //       from parsing the elements correctly for the reference tests.
         if (this.data.multiLine) {
           element = document.createElement('textarea');
+          element.textContent = this.data.fieldValue;
         } else {
           element = document.createElement('input');
           element.type = 'text';
-        }
-
-        element.value = this.data.fieldValue;
+          element.setAttribute('value', this.data.fieldValue);
+        }
+
         element.disabled = this.data.readOnly;
 
         if (this.data.maxLen !== null) {
           element.maxLength = this.data.maxLen;
         }
+
+        if (this.data.comb) {
+          var fieldWidth = this.data.rect[2] - this.data.rect[0];
+          var combWidth = fieldWidth / this.data.maxLen;
+
+          element.classList.add('comb');
+          element.style.letterSpacing = 'calc(' + combWidth + 'px - 1ch)';
+        }
       } else {
         element = document.createElement('div');
         element.textContent = this.data.fieldValue;
         element.style.verticalAlign = 'middle';
         element.style.display = 'table-cell';
 
         var font = null;
         if (this.data.fontRefName) {
--- a/browser/extensions/pdfjs/content/build/pdf.worker.js
+++ b/browser/extensions/pdfjs/content/build/pdf.worker.js
@@ -23,18 +23,18 @@ define('pdfjs-dist/build/pdf.worker', ['
     factory(exports);
   } else {
 factory((root.pdfjsDistBuildPdfWorker = {}));
   }
 }(this, function (exports) {
   // Use strict in our context only - users might not want it
   'use strict';
 
-var pdfjsVersion = '1.5.476';
-var pdfjsBuild = 'c0e82db';
+var pdfjsVersion = '1.5.498';
+var pdfjsBuild = '1564dc3';
 
   var pdfjsFilePath =
     typeof document !== 'undefined' && document.currentScript ?
       document.currentScript.src : null;
 
   var pdfjsLibs = {};
 
   (function pdfjsWrapper() {
@@ -1096,35 +1096,35 @@ var AnnotationFlag = {
   NOVIEW: 0x20,
   READONLY: 0x40,
   LOCKED: 0x80,
   TOGGLENOVIEW: 0x100,
   LOCKEDCONTENTS: 0x200
 };
 
 var AnnotationFieldFlag = {
-  READONLY: 1,
-  REQUIRED: 2,
-  NOEXPORT: 3,
-  MULTILINE: 13,
-  PASSWORD: 14,
-  NOTOGGLETOOFF: 15,
-  RADIO: 16,
-  PUSHBUTTON: 17,
-  COMBO: 18,
-  EDIT: 19,
-  SORT: 20,
-  FILESELECT: 21,
-  MULTISELECT: 22,
-  DONOTSPELLCHECK: 23,
-  DONOTSCROLL: 24,
-  COMB: 25,
-  RICHTEXT: 26,
-  RADIOSINUNISON: 26,
-  COMMITONSELCHANGE: 27,
+  READONLY: 0x0000001,
+  REQUIRED: 0x0000002,
+  NOEXPORT: 0x0000004,
+  MULTILINE: 0x0001000,
+  PASSWORD: 0x0002000,
+  NOTOGGLETOOFF: 0x0004000,
+  RADIO: 0x0008000,
+  PUSHBUTTON: 0x0010000,
+  COMBO: 0x0020000,
+  EDIT: 0x0040000,
+  SORT: 0x0080000,
+  FILESELECT: 0x0100000,
+  MULTISELECT: 0x0200000,
+  DONOTSPELLCHECK: 0x0400000,
+  DONOTSCROLL: 0x0800000,
+  COMB: 0x1000000,
+  RICHTEXT: 0x2000000,
+  RADIOSINUNISON: 0x2000000,
+  COMMITONSELCHANGE: 0x4000000,
 };
 
 var AnnotationBorderStyleType = {
   SOLID: 1,
   DASHED: 2,
   BEVELED: 3,
   INSET: 4,
   UNDERLINE: 5
@@ -10209,17 +10209,17 @@ var error = sharedUtil.error;
  *   (www.w3.org/Graphics/JPEG/itu-t81.pdf)
  * - The JFIF specification can be found in the JPEG File Interchange Format
  *   (www.w3.org/Graphics/JPEG/jfif3.pdf)
  * - The Adobe Application-Specific JPEG markers in the
  *   Supporting the DCT Filters in PostScript Level 2, Technical Note #5116
  *   (partners.adobe.com/public/developer/en/ps/sdk/5116.DCT_Filter.pdf)
  */
 
-var JpegImage = (function jpegImage() {
+var JpegImage = (function JpegImageClosure() {
   var dctZigZag = new Uint8Array([
      0,
      1,  8,
     16,  9,  2,
      3, 10, 17, 24,
     32, 25, 18, 11, 4,
      5, 12, 19, 26, 33, 40,
     48, 41, 34, 27, 20, 13,  6,
@@ -10237,17 +10237,19 @@ var JpegImage = (function jpegImage() {
   var dctSin1  =   799;   // sin(pi/16)
   var dctCos3  =  3406;   // cos(3*pi/16)
   var dctSin3  =  2276;   // sin(3*pi/16)
   var dctCos6  =  1567;   // cos(6*pi/16)
   var dctSin6  =  3784;   // sin(6*pi/16)
   var dctSqrt2 =  5793;   // sqrt(2)
   var dctSqrt1d2 = 2896;  // sqrt(2) / 2
 
-  function constructor() {
+  function JpegImage() {
+    this.decodeTransform = null;
+    this.colorTransform = -1;
   }
 
   function buildHuffmanTable(codeLengths, values) {
     var k = 0, code = [], i, j, length = 16;
     while (length > 0 && !codeLengths[length - 1]) {
       length--;
     }
     code.push({children: [], index: 0});
@@ -10532,16 +10534,22 @@ var JpegImage = (function jpegImage() {
           }
           mcu++;
         }
       }
 
       // find marker
       bitsCount = 0;
       marker = (data[offset] << 8) | data[offset + 1];
+      // Some bad images seem to pad Scan blocks with zero bytes, skip past
+      // those to attempt to find a valid marker (fixes issue4090.pdf).
+      while (data[offset] === 0x00 && offset < data.length - 1) {
+        offset++;
+        marker = (data[offset] << 8) | data[offset + 1];
+      }
       if (marker <= 0xFF00) {
         error('JPEG error: marker was not found');
       }
 
       if (marker >= 0xFFD0 && marker <= 0xFFD7) { // RSTx
         offset += 2;
       } else {
         break;
@@ -10754,17 +10762,17 @@ var JpegImage = (function jpegImage() {
     }
     return component.blockData;
   }
 
   function clamp0to255(a) {
     return a <= 0 ? 0 : a >= 255 ? 255 : a;
   }
 
-  constructor.prototype = {
+  JpegImage.prototype = {
     parse: function parse(data) {
 
       function readUint16() {
         var value = (data[offset] << 8) | data[offset + 1];
         offset += 2;
         return value;
       }
 
@@ -11071,18 +11079,30 @@ var JpegImage = (function jpegImage() {
       return data;
     },
 
     _isColorConversionNeeded: function isColorConversionNeeded() {
       if (this.adobe && this.adobe.transformCode) {
         // The adobe transform marker overrides any previous setting
         return true;
       } else if (this.numComponents === 3) {
+        if (!this.adobe && this.colorTransform === 0) {
+          // If the Adobe transform marker is not present and the image
+          // dictionary has a 'ColorTransform' entry, explicitly set to `0`,
+          // then the colours should *not* be transformed.
+          return false;
+        }
         return true;
-      } else {
+      } else { // `this.numComponents !== 3`
+        if (!this.adobe && this.colorTransform === 1) {
+          // If the Adobe transform marker is not present and the image
+          // dictionary has a 'ColorTransform' entry, explicitly set to `1`,
+          // then the colours should be transformed.
+          return true;
+        }
         return false;
       }
     },
 
     _convertYccToRgb: function convertYccToRgb(data) {
       var Y, Cb, Cr;
       for (var i = 0, length = data.length; i < length; i += 3) {
         Y  = data[i    ];
@@ -11214,34 +11234,34 @@ var JpegImage = (function jpegImage() {
         var offset = 0;
         for (var i = 0; i < dataLength; i++) {
           var grayColor = data[i];
           rgbData[offset++] = grayColor;
           rgbData[offset++] = grayColor;
           rgbData[offset++] = grayColor;
         }
         return rgbData;
-      } else if (this.numComponents === 3) {
+      } else if (this.numComponents === 3 && this._isColorConversionNeeded()) {
         return this._convertYccToRgb(data);
       } else if (this.numComponents === 4) {
         if (this._isColorConversionNeeded()) {
           if (forceRGBoutput) {
             return this._convertYcckToRgb(data);
           } else {
             return this._convertYcckToCmyk(data);
           }
         } else if (forceRGBoutput) {
           return this._convertCmykToRgb(data);
         }
       }
       return data;
     }
   };
 
-  return constructor;
+  return JpegImage;
 })();
 
 exports.JpegImage = JpegImage;
 }));
 
 
 (function (root, factory) {
   {
@@ -18824,16 +18844,17 @@ exports.isStream = isStream;
       root.pdfjsCoreJpx);
   }
 }(this, function (exports, sharedUtil, corePrimitives, coreJbig2, coreJpg,
                   coreJpx) {
 
 var Util = sharedUtil.Util;
 var error = sharedUtil.error;
 var info = sharedUtil.info;
+var isInt = sharedUtil.isInt;
 var isArray = sharedUtil.isArray;
 var createObjectURL = sharedUtil.createObjectURL;
 var shadow = sharedUtil.shadow;
 var warn = sharedUtil.warn;
 var isSpace = sharedUtil.isSpace;
 var Dict = corePrimitives.Dict;
 var isDict = corePrimitives.isDict;
 var Jbig2Image = coreJbig2.Jbig2Image;
@@ -19681,17 +19702,17 @@ var PredictorStream = (function Predicto
 /**
  * Depending on the type of JPEG a JpegStream is handled in different ways. For
  * JPEG's that are supported natively such as DeviceGray and DeviceRGB the image
  * data is stored and then loaded by the browser.  For unsupported JPEG's we use
  * a library to decode these images and the stream behaves like all the other
  * DecodeStreams.
  */
 var JpegStream = (function JpegStreamClosure() {
-  function JpegStream(stream, maybeLength, dict, xref) {
+  function JpegStream(stream, maybeLength, dict) {
     // Some images may contain 'junk' before the SOI (start-of-image) marker.
     // Note: this seems to mainly affect inline images.
     var ch;
     while ((ch = stream.getByte()) !== -1) {
       if (ch === 0xFF) { // Find the first byte of the SOI marker (0xFFD8).
         stream.skip(-1); // Reset the stream position to the SOI.
         break;
       }
@@ -19715,34 +19736,42 @@ var JpegStream = (function JpegStreamClo
 
   JpegStream.prototype.ensureBuffer = function JpegStream_ensureBuffer(req) {
     if (this.bufferLength) {
       return;
     }
     var jpegImage = new JpegImage();
 
     // Checking if values need to be transformed before conversion.
-    if (this.forceRGB && this.dict && isArray(this.dict.get('Decode'))) {
-      var decodeArr = this.dict.getArray('Decode');
+    var decodeArr = this.dict.getArray('Decode', 'D');
+    if (this.forceRGB && isArray(decodeArr)) {
       var bitsPerComponent = this.dict.get('BitsPerComponent') || 8;
       var decodeArrLength = decodeArr.length;
       var transform = new Int32Array(decodeArrLength);
       var transformNeeded = false;
       var maxValue = (1 << bitsPerComponent) - 1;
       for (var i = 0; i < decodeArrLength; i += 2) {
         transform[i] = ((decodeArr[i + 1] - decodeArr[i]) * 256) | 0;
         transform[i + 1] = (decodeArr[i] * maxValue) | 0;
         if (transform[i] !== 256 || transform[i + 1] !== 0) {
           transformNeeded = true;
         }
       }
       if (transformNeeded) {
         jpegImage.decodeTransform = transform;
       }
     }
+    // Fetching the 'ColorTransform' entry, if it exists.
+    var decodeParams = this.dict.get('DecodeParms', 'DP');
+    if (isDict(decodeParams)) {
+      var colorTransform = decodeParams.get('ColorTransform');
+      if (isInt(colorTransform)) {
+        jpegImage.colorTransform = colorTransform;
+      }
+    }
 
     jpegImage.parse(this.bytes);
     var data = jpegImage.getData(this.drawWidth, this.drawHeight,
                                  this.forceRGB);
     this.buffer = data;
     this.bufferLength = data.length;
     this.eof = true;
   };
@@ -19854,17 +19883,17 @@ var Jbig2Stream = (function Jbig2StreamC
   Jbig2Stream.prototype.ensureBuffer = function Jbig2Stream_ensureBuffer(req) {
     if (this.bufferLength) {
       return;
     }
 
     var jbig2Image = new Jbig2Image();
 
     var chunks = [];
-    var decodeParams = this.dict.getArray('DecodeParms');
+    var decodeParams = this.dict.getArray('DecodeParms', 'DP');
 
     // According to the PDF specification, DecodeParms can be either
     // a dictionary, or an array whose elements are dictionaries.
     if (isArray(decodeParams)) {
       if (decodeParams.length > 1) {
         warn('JBIG2 - \'DecodeParms\' array with multiple elements ' +
              'not supported.');
       }
@@ -24658,17 +24687,17 @@ var Parser = (function ParserClosure() {
             return new PredictorStream(
               new LZWStream(stream, maybeLength, earlyChange),
               maybeLength, params);
           }
           return new LZWStream(stream, maybeLength, earlyChange);
         }
         if (name === 'DCTDecode' || name === 'DCT') {
           xrefStreamStats[StreamType.DCT] = true;
-          return new JpegStream(stream, maybeLength, stream.dict, this.xref);
+          return new JpegStream(stream, maybeLength, stream.dict);
         }
         if (name === 'JPXDecode' || name === 'JPX') {
           xrefStreamStats[StreamType.JPX] = true;
           return new JpxStream(stream, maybeLength, stream.dict);
         }
         if (name === 'ASCII85Decode' || name === 'A85') {
           xrefStreamStats[StreamType.A85] = true;
           return new Ascii85Stream(stream, maybeLength);
@@ -30099,17 +30128,24 @@ var Type1Font = (function Type1FontClosu
         }
         charsetArray.push((index >> 8) & 0xff, index & 0xff);
       }
       cff.charset = new CFFCharset(false, 0, [], charsetArray);
 
       var charStringsIndex = new CFFIndex();
       charStringsIndex.add([0x8B, 0x0E]); // .notdef
       for (i = 0; i < count; i++) {
-        charStringsIndex.add(glyphs[i]);
+        var glyph = glyphs[i];
+        // If the CharString outline is empty, replace it with .notdef to
+        // prevent OTS from rejecting the font (fixes bug1252420.pdf).
+        if (glyph.length === 0) {
+          charStringsIndex.add([0x8B, 0x0E]); // .notdef
+          continue;
+        }
+        charStringsIndex.add(glyph);
       }
       cff.charStrings = charStringsIndex;
 
       var privateDict = new CFFPrivateDict();
       privateDict.setByName('Subrs', null); // placeholder
       var fields = [
         'BlueValues',
         'OtherBlues',
@@ -36069,28 +36105,36 @@ var PartialEvaluator = (function Partial
     }
   };
   /**
    * Checks if the image can be decoded and displayed by the browser without any
    * further processing such as color space conversions.
    */
   NativeImageDecoder.isSupported =
       function NativeImageDecoder_isSupported(image, xref, res) {
-    var cs = ColorSpace.parse(image.dict.get('ColorSpace', 'CS'), xref, res);
+    var dict = image.dict;
+    if (dict.has('DecodeParms') || dict.has('DP')) {
+      return false;
+    }
+    var cs = ColorSpace.parse(dict.get('ColorSpace', 'CS'), xref, res);
     return (cs.name === 'DeviceGray' || cs.name === 'DeviceRGB') &&
-           cs.isDefaultDecode(image.dict.getArray('Decode', 'D'));
+           cs.isDefaultDecode(dict.getArray('Decode', 'D'));
   };
   /**
    * Checks if the image can be decoded by the browser.
    */
   NativeImageDecoder.isDecodable =
       function NativeImageDecoder_isDecodable(image, xref, res) {
-    var cs = ColorSpace.parse(image.dict.get('ColorSpace', 'CS'), xref, res);
+    var dict = image.dict;
+    if (dict.has('DecodeParms') || dict.has('DP')) {
+      return false;
+    }
+    var cs = ColorSpace.parse(dict.get('ColorSpace', 'CS'), xref, res);
     return (cs.numComps === 1 || cs.numComps === 3) &&
-           cs.isDefaultDecode(image.dict.getArray('Decode', 'D'));
+           cs.isDefaultDecode(dict.getArray('Decode', 'D'));
   };
 
   function PartialEvaluator(pdfManager, xref, handler, pageIndex,
                             uniquePrefix, idCounters, fontCache, options) {
     this.pdfManager = pdfManager;
     this.xref = xref;
     this.handler = handler;
     this.pageIndex = pageIndex;
@@ -39281,22 +39325,20 @@ var OperatorList = coreEvaluator.Operato
  */
 function AnnotationFactory() {}
 AnnotationFactory.prototype = /** @lends AnnotationFactory.prototype */ {
   /**
    * @param {XRef} xref
    * @param {Object} ref
    * @param {string} uniquePrefix
    * @param {Object} idCounters
-   * @param {boolean} renderInteractiveForms
    * @returns {Annotation}
    */
   create: function AnnotationFactory_create(xref, ref,
-                                            uniquePrefix, idCounters,
-                                            renderInteractiveForms) {
+                                            uniquePrefix, idCounters) {
     var dict = xref.fetchIfRef(ref);
     if (!isDict(dict)) {
       return;
     }
     var id = isRef(ref) ? ref.toString() :
                           'annot_' + (uniquePrefix || '') + (++idCounters.obj);
 
     // Determine the annotation's subtype.
@@ -39305,17 +39347,16 @@ AnnotationFactory.prototype = /** @lends
 
     // Return the right annotation object based on the subtype and field type.
     var parameters = {
       xref: xref,
       dict: dict,
       ref: isRef(ref) ? ref : null,
       subtype: subtype,
       id: id,
-      renderInteractiveForms: renderInteractiveForms,
     };
 
     switch (subtype) {
       case 'Link':
         return new LinkAnnotation(parameters);
 
       case 'Text':
         return new TextAnnotation(parameters);
@@ -39630,17 +39671,18 @@ var Annotation = (function AnnotationClo
                                               resources.xref);
           objectLoader.load().then(function() {
             resolve(resources);
           }, reject);
         }, reject);
       }.bind(this));
     },
 
-    getOperatorList: function Annotation_getOperatorList(evaluator, task) {
+    getOperatorList: function Annotation_getOperatorList(evaluator, task,
+                                                         renderForms) {
       if (!this.appearance) {
         return Promise.resolve(new OperatorList());
       }
 
       var data = this.data;
       var appearanceDict = this.appearance.dict;
       var resourcesPromise = this.loadResources([
         'ExtGState',
@@ -39667,23 +39709,23 @@ var Annotation = (function AnnotationClo
               self.appearance.reset();
               return opList;
             });
         });
     }
   };
 
   Annotation.appendToOperatorList = function Annotation_appendToOperatorList(
-      annotations, opList, partialEvaluator, task, intent) {
+      annotations, opList, partialEvaluator, task, intent, renderForms) {
     var annotationPromises = [];
     for (var i = 0, n = annotations.length; i < n; ++i) {
       if ((intent === 'display' && annotations[i].viewable) ||
           (intent === 'print' && annotations[i].printable)) {
         annotationPromises.push(
-          annotations[i].getOperatorList(partialEvaluator, task));
+          annotations[i].getOperatorList(partialEvaluator, task, renderForms));
       }
     }
     return Promise.all(annotationPromises).then(function(operatorLists) {
       opList.addOp(OPS.beginAnnotations, []);
       for (var i = 0, n = operatorLists.length; i < n; ++i) {
         opList.addOpList(operatorLists[i]);
       }
       opList.addOp(OPS.endAnnotations, []);
@@ -39891,36 +39933,33 @@ var WidgetAnnotation = (function WidgetA
   }
 
   Util.inherit(WidgetAnnotation, Annotation, {
     /**
      * Check if a provided field flag is set.
      *
      * @public
      * @memberof WidgetAnnotation
-     * @param {number} flag - Bit position, numbered from one instead of
-     *                        zero, to check
+     * @param {number} flag - Hexadecimal representation for an annotation
+     *                        field characteristic
      * @return {boolean}
      * @see {@link shared/util.js}
      */
     hasFieldFlag: function WidgetAnnotation_hasFieldFlag(flag) {
-      var mask = 1 << (flag - 1);
-      return !!(this.data.fieldFlags & mask);
+      return !!(this.data.fieldFlags & flag);
     },
   });
 
   return WidgetAnnotation;
 })();
 
 var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() {
   function TextWidgetAnnotation(params) {
     WidgetAnnotation.call(this, params);
 
-    this.renderInteractiveForms = params.renderInteractiveForms;
-
     // Determine the alignment of text in the field.
     var alignment = Util.getInheritableProperty(params.dict, 'Q');
     if (!isInt(alignment) || alignment < 0 || alignment > 2) {
       alignment = null;
     }
     this.data.textAlignment = alignment;
 
     // Determine the maximum length of text in the field.
@@ -39928,31 +39967,38 @@ var TextWidgetAnnotation = (function Tex
     if (!isInt(maximumLength) || maximumLength < 0) {
       maximumLength = null;
     }
     this.data.maxLen = maximumLength;
 
     // Process field flags for the display layer.
     this.data.readOnly = this.hasFieldFlag(AnnotationFieldFlag.READONLY);
     this.data.multiLine = this.hasFieldFlag(AnnotationFieldFlag.MULTILINE);
+    this.data.comb = this.hasFieldFlag(AnnotationFieldFlag.COMB) &&
+                     !this.hasFieldFlag(AnnotationFieldFlag.MULTILINE) &&
+                     !this.hasFieldFlag(AnnotationFieldFlag.PASSWORD) &&
+                     !this.hasFieldFlag(AnnotationFieldFlag.FILESELECT) &&
+                     this.data.maxLen !== null;
   }
 
   Util.inherit(TextWidgetAnnotation, WidgetAnnotation, {
-    getOperatorList: function TextWidgetAnnotation_getOperatorList(evaluator,
-                                                                   task) {
+    getOperatorList:
+        function TextWidgetAnnotation_getOperatorList(evaluator, task,
+                                                      renderForms) {
       var operatorList = new OperatorList();
 
       // Do not render form elements on the canvas when interactive forms are
       // enabled. The display layer is responsible for rendering them instead.
-      if (this.renderInteractiveForms) {
+      if (renderForms) {
         return Promise.resolve(operatorList);
       }
 
       if (this.appearance) {
-        return Annotation.prototype.getOperatorList.call(this, evaluator, task);
+        return Annotation.prototype.getOperatorList.call(this, evaluator, task,
+                                                         renderForms);
       }
 
       // Even if there is an appearance stream, ignore it. This is the
       // behaviour used by Adobe Reader.
       if (!this.data.defaultAppearance) {
         return Promise.resolve(operatorList);
       }
 
@@ -40443,31 +40489,30 @@ var Page = (function PageClosure() {
           intent: intent
         });
         return partialEvaluator.getOperatorList(contentStream, task,
           self.resources, opList).then(function () {
             return opList;
           });
       });
 
-      this.renderInteractiveForms = renderInteractiveForms;
-
       var annotationsPromise = pdfManager.ensure(this, 'annotations');
       return Promise.all([pageListPromise, annotationsPromise]).then(
           function(datas) {
         var pageOpList = datas[0];
         var annotations = datas[1];
 
         if (annotations.length === 0) {
           pageOpList.flush(true);
           return pageOpList;
         }
 
         var annotationsReadyPromise = Annotation.appendToOperatorList(
-          annotations, pageOpList, partialEvaluator, task, intent);
+          annotations, pageOpList, partialEvaluator, task, intent,
+          renderInteractiveForms);
         return annotationsReadyPromise.then(function () {
           pageOpList.flush(true);
           return pageOpList;
         });
       });
     },
 
     extractTextContent: function Page_extractTextContent(task,
@@ -40528,18 +40573,17 @@ var Page = (function PageClosure() {
     get annotations() {
       var annotations = [];
       var annotationRefs = this.getInheritedPageProp('Annots') || [];
       var annotationFactory = new AnnotationFactory();
       for (var i = 0, n = annotationRefs.length; i < n; ++i) {
         var annotationRef = annotationRefs[i];
         var annotation = annotationFactory.create(this.xref, annotationRef,
                                                   this.uniquePrefix,
-                                                  this.idCounters,
-                                                  this.renderInteractiveForms);
+                                                  this.idCounters);
         if (annotation) {
           annotations.push(annotation);
         }
       }
       return shadow(this, 'annotations', annotations);
     }
   };
 
--- a/browser/extensions/pdfjs/content/web/viewer.css
+++ b/browser/extensions/pdfjs/content/web/viewer.css
@@ -132,16 +132,32 @@
 }
 
 .annotationLayer .textWidgetAnnotation input:focus,
 .annotationLayer .textWidgetAnnotation textarea:focus {
   background: none;
   border: 1px solid transparent;
 }
 
+.annotationLayer .textWidgetAnnotation input.comb {
+  font-family: monospace;
+  padding-left: 2px;
+  padding-right: 0;
+}
+
+.annotationLayer .textWidgetAnnotation input.comb:focus {
+  /*
+   * Letter spacing is placed on the right side of each character. Hence, the
+   * letter spacing of the last character may be placed outside the visible
+   * area, causing horizontal scrolling. We avoid this by extending the width
+   * when the element has focus and revert this when it loses focus.
+   */
+  width: 115%;
+}
+
 .annotationLayer .popupWrapper {
   position: absolute;
   width: 20em;
 }
 
 .annotationLayer .popup {
   position: absolute;
   z-index: 200;
--- a/browser/extensions/pdfjs/content/web/viewer.js
+++ b/browser/extensions/pdfjs/content/web/viewer.js
@@ -368,404 +368,16 @@ var OverlayManager = {
 };
 
 exports.OverlayManager = OverlayManager;
 }));
 
 
 (function (root, factory) {
   {
-    factory((root.pdfjsWebPDFPresentationMode = {}));
-  }
-}(this, function (exports) {
-
-var DELAY_BEFORE_RESETTING_SWITCH_IN_PROGRESS = 1500; // in ms
-var DELAY_BEFORE_HIDING_CONTROLS = 3000; // in ms
-var ACTIVE_SELECTOR = 'pdfPresentationMode';
-var CONTROLS_SELECTOR = 'pdfPresentationModeControls';
-
-/**
- * @typedef {Object} PDFPresentationModeOptions
- * @property {HTMLDivElement} container - The container for the viewer element.
- * @property {HTMLDivElement} viewer - (optional) The viewer element.
- * @property {PDFViewer} pdfViewer - The document viewer.
- * @property {EventBus} eventBus - The application event bus.
- * @property {Array} contextMenuItems - (optional) The menuitems that are added
- *   to the context menu in Presentation Mode.
- */
-
-/**
- * @class
- */
-var PDFPresentationMode = (function PDFPresentationModeClosure() {
-  /**
-   * @constructs PDFPresentationMode
-   * @param {PDFPresentationModeOptions} options
-   */
-  function PDFPresentationMode(options) {
-    this.container = options.container;
-    this.viewer = options.viewer || options.container.firstElementChild;
-    this.pdfViewer = options.pdfViewer;
-    this.eventBus = options.eventBus;
-    var contextMenuItems = options.contextMenuItems || null;
-
-    this.active = false;
-    this.args = null;
-    this.contextMenuOpen = false;
-    this.mouseScrollTimeStamp = 0;
-    this.mouseScrollDelta = 0;
-
-    if (contextMenuItems) {
-      contextMenuItems.contextFirstPage.addEventListener('click',
-          function PDFPresentationMode_contextFirstPageClick(e) {
-        this.contextMenuOpen = false;
-        this.eventBus.dispatch('firstpage');
-      }.bind(this));
-      contextMenuItems.contextLastPage.addEventListener('click',
-          function PDFPresentationMode_contextLastPageClick(e) {
-        this.contextMenuOpen = false;
-        this.eventBus.dispatch('lastpage');
-      }.bind(this));
-      contextMenuItems.contextPageRotateCw.addEventListener('click',
-          function PDFPresentationMode_contextPageRotateCwClick(e) {
-        this.contextMenuOpen = false;
-        this.eventBus.dispatch('rotatecw');
-      }.bind(this));
-      contextMenuItems.contextPageRotateCcw.addEventListener('click',
-          function PDFPresentationMode_contextPageRotateCcwClick(e) {
-        this.contextMenuOpen = false;
-        this.eventBus.dispatch('rotateccw');
-      }.bind(this));
-    }
-  }
-
-  PDFPresentationMode.prototype = {
-    /**
-     * Request the browser to enter fullscreen mode.
-     * @returns {boolean} Indicating if the request was successful.
-     */
-    request: function PDFPresentationMode_request() {
-      if (this.switchInProgress || this.active ||
-          !this.viewer.hasChildNodes()) {
-        return false;
-      }
-      this._addFullscreenChangeListeners();
-      this._setSwitchInProgress();
-      this._notifyStateChange();
-
-      if (this.container.requestFullscreen) {
-        this.container.requestFullscreen();
-      } else if (this.container.mozRequestFullScreen) {
-        this.container.mozRequestFullScreen();
-      } else if (this.container.webkitRequestFullscreen) {
-        this.container.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
-      } else if (this.container.msRequestFullscreen) {
-        this.container.msRequestFullscreen();
-      } else {
-        return false;
-      }
-
-      this.args = {
-        page: this.pdfViewer.currentPageNumber,
-        previousScale: this.pdfViewer.currentScaleValue,
-      };
-
-      return true;
-    },
-
-    /**
-     * Switches page when the user scrolls (using a scroll wheel or a touchpad)
-     * with large enough motion, to prevent accidental page switches.
-     * @param {number} delta - The delta value from the mouse event.
-     */
-    mouseScroll: function PDFPresentationMode_mouseScroll(delta) {
-      if (!this.active) {
-        return;
-      }
-      var MOUSE_SCROLL_COOLDOWN_TIME = 50;
-      var PAGE_SWITCH_THRESHOLD = 120;
-      var PageSwitchDirection = {
-        UP: -1,
-        DOWN: 1
-      };
-
-      var currentTime = (new Date()).getTime();
-      var storedTime = this.mouseScrollTimeStamp;
-
-      // If we've already switched page, avoid accidentally switching again.
-      if (currentTime > storedTime &&
-          currentTime - storedTime < MOUSE_SCROLL_COOLDOWN_TIME) {
-        return;
-      }
-      // If the scroll direction changed, reset the accumulated scroll delta.
-      if ((this.mouseScrollDelta > 0 && delta < 0) ||
-          (this.mouseScrollDelta < 0 && delta > 0)) {
-        this._resetMouseScrollState();
-      }
-      this.mouseScrollDelta += delta;
-
-      if (Math.abs(this.mouseScrollDelta) >= PAGE_SWITCH_THRESHOLD) {
-        var pageSwitchDirection = (this.mouseScrollDelta > 0) ?
-          PageSwitchDirection.UP : PageSwitchDirection.DOWN;
-        var page = this.pdfViewer.currentPageNumber;
-        this._resetMouseScrollState();
-
-        // If we're at the first/last page, we don't need to do anything.
-        if ((page === 1 && pageSwitchDirection === PageSwitchDirection.UP) ||
-            (page === this.pdfViewer.pagesCount &&
-             pageSwitchDirection === PageSwitchDirection.DOWN)) {
-          return;
-        }
-        this.pdfViewer.currentPageNumber = (page + pageSwitchDirection);
-        this.mouseScrollTimeStamp = currentTime;
-      }
-    },
-
-    get isFullscreen() {
-      return !!(document.fullscreenElement ||
-                document.mozFullScreen ||
-                document.webkitIsFullScreen ||
-                document.msFullscreenElement);
-    },
-
-    /**
-     * @private
-     */
-    _notifyStateChange: function PDFPresentationMode_notifyStateChange() {
-      this.eventBus.dispatch('presentationmodechanged', {
-        source: this,
-        active: this.active,
-        switchInProgress: !!this.switchInProgress
-      });
-    },
-
-    /**
-     * Used to initialize a timeout when requesting Presentation Mode,
-     * i.e. when the browser is requested to enter fullscreen mode.
-     * This timeout is used to prevent the current page from being scrolled
-     * partially, or completely, out of view when entering Presentation Mode.
-     * NOTE: This issue seems limited to certain zoom levels (e.g. page-width).
-     * @private
-     */
-    _setSwitchInProgress: function PDFPresentationMode_setSwitchInProgress() {
-      if (this.switchInProgress) {
-        clearTimeout(this.switchInProgress);
-      }
-      this.switchInProgress = setTimeout(function switchInProgressTimeout() {
-        this._removeFullscreenChangeListeners();
-        delete this.switchInProgress;
-        this._notifyStateChange();
-      }.bind(this), DELAY_BEFORE_RESETTING_SWITCH_IN_PROGRESS);
-    },
-
-    /**
-     * @private
-     */
-    _resetSwitchInProgress:
-        function PDFPresentationMode_resetSwitchInProgress() {
-      if (this.switchInProgress) {
-        clearTimeout(this.switchInProgress);
-        delete this.switchInProgress;
-      }
-    },
-
-    /**
-     * @private
-     */
-    _enter: function PDFPresentationMode_enter() {
-      this.active = true;
-      this._resetSwitchInProgress();
-      this._notifyStateChange();
-      this.container.classList.add(ACTIVE_SELECTOR);
-
-      // Ensure that the correct page is scrolled into view when entering
-      // Presentation Mode, by waiting until fullscreen mode in enabled.
-      setTimeout(function enterPresentationModeTimeout() {
-        this.pdfViewer.currentPageNumber = this.args.page;
-        this.pdfViewer.currentScaleValue = 'page-fit';
-      }.bind(this), 0);
-
-      this._addWindowListeners();
-      this._showControls();
-      this.contextMenuOpen = false;
-      this.container.setAttribute('contextmenu', 'viewerContextMenu');
-
-      // Text selection is disabled in Presentation Mode, thus it's not possible
-      // for the user to deselect text that is selected (e.g. with "Select all")
-      // when entering Presentation Mode, hence we remove any active selection.
-      window.getSelection().removeAllRanges();
-    },
-
-    /**
-     * @private
-     */
-    _exit: function PDFPresentationMode_exit() {
-      var page = this.pdfViewer.currentPageNumber;
-      this.container.classList.remove(ACTIVE_SELECTOR);
-
-      // Ensure that the correct page is scrolled into view when exiting
-      // Presentation Mode, by waiting until fullscreen mode is disabled.
-      setTimeout(function exitPresentationModeTimeout() {
-        this.active = false;
-        this._removeFullscreenChangeListeners();
-        this._notifyStateChange();
-
-        this.pdfViewer.currentScaleValue = this.args.previousScale;
-        this.pdfViewer.currentPageNumber = page;
-        this.args = null;
-      }.bind(this), 0);
-
-      this._removeWindowListeners();
-      this._hideControls();
-      this._resetMouseScrollState();
-      this.container.removeAttribute('contextmenu');
-      this.contextMenuOpen = false;
-    },
-
-    /**
-     * @private
-     */
-    _mouseDown: function PDFPresentationMode_mouseDown(evt) {
-      if (this.contextMenuOpen) {
-        this.contextMenuOpen = false;
-        evt.preventDefault();
-        return;
-      }
-      if (evt.button === 0) {
-        // Enable clicking of links in presentation mode. Please note:
-        // Only links pointing to destinations in the current PDF document work.
-        var isInternalLink = (evt.target.href &&
-                              evt.target.classList.contains('internalLink'));
-        if (!isInternalLink) {
-          // Unless an internal link was clicked, advance one page.
-          evt.preventDefault();
-          this.pdfViewer.currentPageNumber += (evt.shiftKey ? -1 : 1);
-        }
-      }
-    },
-
-    /**
-     * @private
-     */
-    _contextMenu: function PDFPresentationMode_contextMenu() {
-      this.contextMenuOpen = true;
-    },
-
-    /**
-     * @private
-     */
-    _showControls: function PDFPresentationMode_showControls() {
-      if (this.controlsTimeout) {
-        clearTimeout(this.controlsTimeout);
-      } else {
-        this.container.classList.add(CONTROLS_SELECTOR);
-      }
-      this.controlsTimeout = setTimeout(function showControlsTimeout() {
-        this.container.classList.remove(CONTROLS_SELECTOR);
-        delete this.controlsTimeout;
-      }.bind(this), DELAY_BEFORE_HIDING_CONTROLS);
-    },
-
-    /**
-     * @private
-     */
-    _hideControls: function PDFPresentationMode_hideControls() {
-      if (!this.controlsTimeout) {
-        return;
-      }
-      clearTimeout(this.controlsTimeout);
-      this.container.classList.remove(CONTROLS_SELECTOR);
-      delete this.controlsTimeout;
-    },
-
-    /**
-     * Resets the properties used for tracking mouse scrolling events.
-     * @private
-     */
-    _resetMouseScrollState:
-        function PDFPresentationMode_resetMouseScrollState() {
-      this.mouseScrollTimeStamp = 0;
-      this.mouseScrollDelta = 0;
-    },
-
-    /**
-     * @private
-     */
-    _addWindowListeners: function PDFPresentationMode_addWindowListeners() {
-      this.showControlsBind = this._showControls.bind(this);
-      this.mouseDownBind = this._mouseDown.bind(this);
-      this.resetMouseScrollStateBind = this._resetMouseScrollState.bind(this);
-      this.contextMenuBind = this._contextMenu.bind(this);
-
-      window.addEventListener('mousemove', this.showControlsBind);
-      window.addEventListener('mousedown', this.mouseDownBind);
-      window.addEventListener('keydown', this.resetMouseScrollStateBind);
-      window.addEventListener('contextmenu', this.contextMenuBind);
-    },
-
-    /**
-     * @private
-     */
-    _removeWindowListeners:
-        function PDFPresentationMode_removeWindowListeners() {
-      window.removeEventListener('mousemove', this.showControlsBind);
-      window.removeEventListener('mousedown', this.mouseDownBind);
-      window.removeEventListener('keydown', this.resetMouseScrollStateBind);
-      window.removeEventListener('contextmenu', this.contextMenuBind);
-
-      delete this.showControlsBind;
-      delete this.mouseDownBind;
-      delete this.resetMouseScrollStateBind;
-      delete this.contextMenuBind;
-    },
-
-    /**
-     * @private
-     */
-    _fullscreenChange: function PDFPresentationMode_fullscreenChange() {
-      if (this.isFullscreen) {
-        this._enter();
-      } else {
-        this._exit();
-      }
-    },
-
-    /**
-     * @private
-     */
-    _addFullscreenChangeListeners:
-        function PDFPresentationMode_addFullscreenChangeListeners() {
-      this.fullscreenChangeBind = this._fullscreenChange.bind(this);
-
-      window.addEventListener('fullscreenchange', this.fullscreenChangeBind);
-      window.addEventListener('mozfullscreenchange', this.fullscreenChangeBind);
-    },
-
-    /**
-     * @private
-     */
-    _removeFullscreenChangeListeners:
-        function PDFPresentationMode_removeFullscreenChangeListeners() {
-      window.removeEventListener('fullscreenchange', this.fullscreenChangeBind);
-      window.removeEventListener('mozfullscreenchange',
-                                 this.fullscreenChangeBind);
-
-      delete this.fullscreenChangeBind;
-    }
-  };
-
-  return PDFPresentationMode;
-})();
-
-exports.PDFPresentationMode = PDFPresentationMode;
-}));
-
-
-(function (root, factory) {
-  {
     factory((root.pdfjsWebPDFRenderingQueue = {}));
   }
 }(this, function (exports) {
 
 var CLEANUP_TIMEOUT = 30000;
 
 var RenderingStates = {
   INITIAL: 0,
@@ -2342,16 +1954,38 @@ function getPDFFileNameFromURL(url) {
         // URIError "Malformed URI", e.g. for "%AA.pdf"
         // TypeError "null has no properties", e.g. for "%2F.pdf"
       }
     }
   }
   return suggestedFilename || 'document.pdf';
 }
 
+function normalizeWheelEventDelta(evt) {
+  var delta = Math.sqrt(evt.deltaX * evt.deltaX + evt.deltaY * evt.deltaY);
+  var angle = Math.atan2(evt.deltaY, evt.deltaX);
+  if (-0.25 * Math.PI < angle && angle < 0.75 * Math.PI) {
+    // All that is left-up oriented has to change the sign.
+    delta = -delta;
+  }
+
+  var MOUSE_DOM_DELTA_PIXEL_MODE = 0;
+  var MOUSE_DOM_DELTA_LINE_MODE = 1;
+  var MOUSE_PIXELS_PER_LINE = 30;
+  var MOUSE_LINES_PER_PAGE = 30;
+
+  // Converts delta to per-page units
+  if (evt.deltaMode === MOUSE_DOM_DELTA_PIXEL_MODE) {
+    delta /= MOUSE_PIXELS_PER_LINE * MOUSE_LINES_PER_PAGE;
+  } else if (evt.deltaMode === MOUSE_DOM_DELTA_LINE_MODE) {
+    delta /= MOUSE_LINES_PER_PAGE;
+  }
+  return delta;
+}
+
 /**
  * Simple event bus for an application. Listeners are attached using the
  * `on` and `off` methods. To raise an event, the `dispatch` method shall be
  * used.
  */
 var EventBus = (function EventBusClosure() {
   function EventBus() {
     this._listeners = Object.create(null);
@@ -2487,16 +2121,17 @@ exports.noContextMenuHandler = noContext
 exports.parseQueryString = parseQueryString;
 exports.getVisibleElements = getVisibleElements;
 exports.roundToDivide = roundToDivide;
 exports.approximateFraction = approximateFraction;
 exports.getOutputScale = getOutputScale;
 exports.scrollIntoView = scrollIntoView;
 exports.watchScroll = watchScroll;
 exports.binarySearchFirstItem = binarySearchFirstItem;
+exports.normalizeWheelEventDelta = normalizeWheelEventDelta;
 }));
 
 
 (function (root, factory) {
   {
     factory((root.pdfjsWebDOMEvents = {}), root.pdfjsWebUIUtils);
   }
 }(this, function (exports, uiUtils) {
@@ -3444,16 +3079,503 @@ var PDFFindController = (function PDFFin
 
 exports.FindStates = FindStates;
 exports.PDFFindController = PDFFindController;
 }));
 
 
 (function (root, factory) {
   {
+    factory((root.pdfjsWebPDFPresentationMode = {}), root.pdfjsWebUIUtils);
+  }
+}(this, function (exports, uiUtils) {
+var normalizeWheelEventDelta = uiUtils.normalizeWheelEventDelta;
+
+var DELAY_BEFORE_RESETTING_SWITCH_IN_PROGRESS = 1500; // in ms
+var DELAY_BEFORE_HIDING_CONTROLS = 3000; // in ms
+var ACTIVE_SELECTOR = 'pdfPresentationMode';
+var CONTROLS_SELECTOR = 'pdfPresentationModeControls';
+
+/**
+ * @typedef {Object} PDFPresentationModeOptions
+ * @property {HTMLDivElement} container - The container for the viewer element.
+ * @property {HTMLDivElement} viewer - (optional) The viewer element.
+ * @property {PDFViewer} pdfViewer - The document viewer.
+ * @property {EventBus} eventBus - The application event bus.
+ * @property {Array} contextMenuItems - (optional) The menuitems that are added
+ *   to the context menu in Presentation Mode.
+ */
+
+/**
+ * @class
+ */
+var PDFPresentationMode = (function PDFPresentationModeClosure() {
+  /**
+   * @constructs PDFPresentationMode
+   * @param {PDFPresentationModeOptions} options
+   */
+  function PDFPresentationMode(options) {
+    this.container = options.container;
+    this.viewer = options.viewer || options.container.firstElementChild;
+    this.pdfViewer = options.pdfViewer;
+    this.eventBus = options.eventBus;
+    var contextMenuItems = options.contextMenuItems || null;
+
+    this.active = false;
+    this.args = null;
+    this.contextMenuOpen = false;
+    this.mouseScrollTimeStamp = 0;
+    this.mouseScrollDelta = 0;
+    this.touchSwipeState = null;
+
+    if (contextMenuItems) {
+      contextMenuItems.contextFirstPage.addEventListener('click',
+          function PDFPresentationMode_contextFirstPageClick(e) {
+        this.contextMenuOpen = false;
+        this.eventBus.dispatch('firstpage');
+      }.bind(this));
+      contextMenuItems.contextLastPage.addEventListener('click',
+          function PDFPresentationMode_contextLastPageClick(e) {
+        this.contextMenuOpen = false;
+        this.eventBus.dispatch('lastpage');
+      }.bind(this));
+      contextMenuItems.contextPageRotateCw.addEventListener('click',
+          function PDFPresentationMode_contextPageRotateCwClick(e) {
+        this.contextMenuOpen = false;
+        this.eventBus.dispatch('rotatecw');
+      }.bind(this));
+      contextMenuItems.contextPageRotateCcw.addEventListener('click',
+          function PDFPresentationMode_contextPageRotateCcwClick(e) {
+        this.contextMenuOpen = false;
+        this.eventBus.dispatch('rotateccw');
+      }.bind(this));
+    }
+  }
+
+  PDFPresentationMode.prototype = {
+    /**
+     * Request the browser to enter fullscreen mode.
+     * @returns {boolean} Indicating if the request was successful.
+     */
+    request: function PDFPresentationMode_request() {
+      if (this.switchInProgress || this.active ||
+          !this.viewer.hasChildNodes()) {
+        return false;
+      }
+      this._addFullscreenChangeListeners();
+      this._setSwitchInProgress();
+      this._notifyStateChange();
+
+      if (this.container.requestFullscreen) {
+        this.container.requestFullscreen();
+      } else if (this.container.mozRequestFullScreen) {
+        this.container.mozRequestFullScreen();
+      } else if (this.container.webkitRequestFullscreen) {
+        this.container.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
+      } else if (this.container.msRequestFullscreen) {
+        this.container.msRequestFullscreen();
+      } else {
+        return false;
+      }
+
+      this.args = {
+        page: this.pdfViewer.currentPageNumber,
+        previousScale: this.pdfViewer.currentScaleValue,
+      };
+
+      return true;
+    },
+
+    /**
+     * @private
+     */
+    _mouseWheel: function PDFPresentationMode_mouseWheel(evt) {
+      if (!this.active) {
+        return;
+      }
+
+      evt.preventDefault();
+
+      var delta = normalizeWheelEventDelta(evt);
+
+      var MOUSE_SCROLL_COOLDOWN_TIME = 50;
+      var PAGE_SWITCH_THRESHOLD = 0.1;
+
+      var currentTime = (new Date()).getTime();
+      var storedTime = this.mouseScrollTimeStamp;
+
+      // If we've already switched page, avoid accidentally switching again.
+      if (currentTime > storedTime &&
+          currentTime - storedTime < MOUSE_SCROLL_COOLDOWN_TIME) {
+        return;
+      }
+      // If the scroll direction changed, reset the accumulated scroll delta.
+      if ((this.mouseScrollDelta > 0 && delta < 0) ||
+          (this.mouseScrollDelta < 0 && delta > 0)) {
+        this._resetMouseScrollState();
+      }
+      this.mouseScrollDelta += delta;
+
+      if (Math.abs(this.mouseScrollDelta) >= PAGE_SWITCH_THRESHOLD) {
+        var totalDelta = this.mouseScrollDelta;
+        this._resetMouseScrollState();
+        var success = totalDelta > 0 ? this._goToPreviousPage()
+                                     : this._goToNextPage();
+        if (success) {
+          this.mouseScrollTimeStamp = currentTime;
+        }
+      }
+    },
+
+    get isFullscreen() {
+      return !!(document.fullscreenElement ||
+                document.mozFullScreen ||
+                document.webkitIsFullScreen ||
+                document.msFullscreenElement);
+    },
+
+    /**
+     * @private
+     */
+    _goToPreviousPage: function PDFPresentationMode_goToPreviousPage() {
+      var page = this.pdfViewer.currentPageNumber;
+      // If we're at the first page, we don't need to do anything.
+      if (page <= 1) {
+        return false;
+      }
+      this.pdfViewer.currentPageNumber = (page - 1);
+      return true;
+    },
+
+    /**
+     * @private
+     */
+    _goToNextPage: function PDFPresentationMode_goToNextPage() {
+      var page = this.pdfViewer.currentPageNumber;
+      // If we're at the last page, we don't need to do anything.
+      if (page >= this.pdfViewer.pagesCount) {
+        return false;
+      }
+      this.pdfViewer.currentPageNumber = (page + 1);
+      return true;
+    },
+
+    /**
+     * @private
+     */
+    _notifyStateChange: function PDFPresentationMode_notifyStateChange() {
+      this.eventBus.dispatch('presentationmodechanged', {
+        source: this,
+        active: this.active,
+        switchInProgress: !!this.switchInProgress
+      });
+    },
+
+    /**
+     * Used to initialize a timeout when requesting Presentation Mode,
+     * i.e. when the browser is requested to enter fullscreen mode.
+     * This timeout is used to prevent the current page from being scrolled
+     * partially, or completely, out of view when entering Presentation Mode.
+     * NOTE: This issue seems limited to certain zoom levels (e.g. page-width).
+     * @private
+     */
+    _setSwitchInProgress: function PDFPresentationMode_setSwitchInProgress() {
+      if (this.switchInProgress) {
+        clearTimeout(this.switchInProgress);
+      }
+      this.switchInProgress = setTimeout(function switchInProgressTimeout() {
+        this._removeFullscreenChangeListeners();
+        delete this.switchInProgress;
+        this._notifyStateChange();
+      }.bind(this), DELAY_BEFORE_RESETTING_SWITCH_IN_PROGRESS);
+    },
+
+    /**
+     * @private
+     */
+    _resetSwitchInProgress:
+        function PDFPresentationMode_resetSwitchInProgress() {
+      if (this.switchInProgress) {
+        clearTimeout(this.switchInProgress);
+        delete this.switchInProgress;
+      }
+    },
+
+    /**
+     * @private
+     */
+    _enter: function PDFPresentationMode_enter() {
+      this.active = true;
+      this._resetSwitchInProgress();
+      this._notifyStateChange();
+      this.container.classList.add(ACTIVE_SELECTOR);
+
+      // Ensure that the correct page is scrolled into view when entering
+      // Presentation Mode, by waiting until fullscreen mode in enabled.
+      setTimeout(function enterPresentationModeTimeout() {
+        this.pdfViewer.currentPageNumber = this.args.page;
+        this.pdfViewer.currentScaleValue = 'page-fit';
+      }.bind(this), 0);
+
+      this._addWindowListeners();
+      this._showControls();
+      this.contextMenuOpen = false;
+      this.container.setAttribute('contextmenu', 'viewerContextMenu');
+
+      // Text selection is disabled in Presentation Mode, thus it's not possible
+      // for the user to deselect text that is selected (e.g. with "Select all")
+      // when entering Presentation Mode, hence we remove any active selection.
+      window.getSelection().removeAllRanges();
+    },
+
+    /**
+     * @private
+     */
+    _exit: function PDFPresentationMode_exit() {
+      var page = this.pdfViewer.currentPageNumber;
+      this.container.classList.remove(ACTIVE_SELECTOR);
+
+      // Ensure that the correct page is scrolled into view when exiting
+      // Presentation Mode, by waiting until fullscreen mode is disabled.
+      setTimeout(function exitPresentationModeTimeout() {
+        this.active = false;
+        this._removeFullscreenChangeListeners();
+        this._notifyStateChange();
+
+        this.pdfViewer.currentScaleValue = this.args.previousScale;
+        this.pdfViewer.currentPageNumber = page;
+        this.args = null;
+      }.bind(this), 0);
+
+      this._removeWindowListeners();
+      this._hideControls();
+      this._resetMouseScrollState();
+      this.container.removeAttribute('contextmenu');
+      this.contextMenuOpen = false;
+    },
+
+    /**
+     * @private
+     */
+    _mouseDown: function PDFPresentationMode_mouseDown(evt) {
+      if (this.contextMenuOpen) {
+        this.contextMenuOpen = false;
+        evt.preventDefault();
+        return;
+      }
+      if (evt.button === 0) {
+        // Enable clicking of links in presentation mode. Please note:
+        // Only links pointing to destinations in the current PDF document work.
+        var isInternalLink = (evt.target.href &&
+                              evt.target.classList.contains('internalLink'));
+        if (!isInternalLink) {
+          // Unless an internal link was clicked, advance one page.
+          evt.preventDefault();
+          this.pdfViewer.currentPageNumber += (evt.shiftKey ? -1 : 1);
+        }
+      }
+    },
+
+    /**
+     * @private
+     */
+    _contextMenu: function PDFPresentationMode_contextMenu() {
+      this.contextMenuOpen = true;
+    },
+
+    /**
+     * @private
+     */
+    _showControls: function PDFPresentationMode_showControls() {
+      if (this.controlsTimeout) {
+        clearTimeout(this.controlsTimeout);
+      } else {
+        this.container.classList.add(CONTROLS_SELECTOR);
+      }
+      this.controlsTimeout = setTimeout(function showControlsTimeout() {
+        this.container.classList.remove(CONTROLS_SELECTOR);
+        delete this.controlsTimeout;
+      }.bind(this), DELAY_BEFORE_HIDING_CONTROLS);
+    },
+
+    /**
+     * @private
+     */
+    _hideControls: function PDFPresentationMode_hideControls() {
+      if (!this.controlsTimeout) {
+        return;
+      }
+      clearTimeout(this.controlsTimeout);
+      this.container.classList.remove(CONTROLS_SELECTOR);
+      delete this.controlsTimeout;
+    },
+
+    /**
+     * Resets the properties used for tracking mouse scrolling events.
+     * @private
+     */
+    _resetMouseScrollState:
+        function PDFPresentationMode_resetMouseScrollState() {
+      this.mouseScrollTimeStamp = 0;
+      this.mouseScrollDelta = 0;
+    },
+
+    /**
+     * @private
+     */
+    _touchSwipe: function PDFPresentationMode_touchSwipe(evt) {
+      if (!this.active) {
+        return;
+      }
+
+      // Must move at least these many CSS pixels for it to count as a swipe
+      var SWIPE_MIN_DISTANCE_THRESHOLD = 50;
+      // The swipe angle is allowed to deviate from the x or y axis by this much
+      // before it is not considered a swipe in that direction any more.
+      var SWIPE_ANGLE_THRESHOLD = Math.PI / 6;
+
+      if (evt.touches.length > 1) {
+        // Multiple touch points detected, cancel the swipe.
+        this.touchSwipeState = null;
+        return;
+      }
+      switch (evt.type) {
+        case 'touchstart':
+          this.touchSwipeState = {
+            startX: evt.touches[0].pageX,
+            startY: evt.touches[0].pageY,
+            endX: evt.touches[0].pageX,
+            endY: evt.touches[0].pageY
+          };
+          break;
+        case 'touchmove':
+          if (this.touchSwipeState === null) {
+            return;
+          }
+          this.touchSwipeState.endX = evt.touches[0].pageX;
+          this.touchSwipeState.endY = evt.touches[0].pageY;
+          // Do a preventDefault to avoid the swipe from triggering browser
+          // gestures (Chrome in particular has some sort of swipe gesture in
+          // fullscreen mode).
+          evt.preventDefault();
+          break;
+        case 'touchend':
+          if (this.touchSwipeState === null) {
+            return;
+          }
+          var delta = 0;
+          var dx = this.touchSwipeState.endX - this.touchSwipeState.startX;
+          var dy = this.touchSwipeState.endY - this.touchSwipeState.startY;
+          var absAngle = Math.abs(Math.atan2(dy, dx));
+          if (Math.abs(dx) > SWIPE_MIN_DISTANCE_THRESHOLD &&
+              (absAngle <= SWIPE_ANGLE_THRESHOLD ||
+               absAngle >= (Math.PI - SWIPE_ANGLE_THRESHOLD))) {
+            // horizontal swipe
+            delta = dx;
+          } else if (Math.abs(dy) > SWIPE_MIN_DISTANCE_THRESHOLD &&
+              Math.abs(absAngle - (Math.PI / 2)) <= SWIPE_ANGLE_THRESHOLD) {
+            // vertical swipe
+            delta = dy;
+          }
+          if (delta > 0) {
+            this._goToPreviousPage();
+          } else if (delta < 0) {
+            this._goToNextPage();
+          }
+          break;
+      }
+    },
+
+    /**
+     * @private
+     */
+    _addWindowListeners: function PDFPresentationMode_addWindowListeners() {
+      this.showControlsBind = this._showControls.bind(this);
+      this.mouseDownBind = this._mouseDown.bind(this);
+      this.mouseWheelBind = this._mouseWheel.bind(this);
+      this.resetMouseScrollStateBind = this._resetMouseScrollState.bind(this);
+      this.contextMenuBind = this._contextMenu.bind(this);
+      this.touchSwipeBind = this._touchSwipe.bind(this);
+
+      window.addEventListener('mousemove', this.showControlsBind);
+      window.addEventListener('mousedown', this.mouseDownBind);
+      window.addEventListener('wheel', this.mouseWheelBind);
+      window.addEventListener('keydown', this.resetMouseScrollStateBind);
+      window.addEventListener('contextmenu', this.contextMenuBind);
+      window.addEventListener('touchstart', this.touchSwipeBind);
+      window.addEventListener('touchmove', this.touchSwipeBind);
+      window.addEventListener('touchend', this.touchSwipeBind);
+    },
+
+    /**
+     * @private
+     */
+    _removeWindowListeners:
+        function PDFPresentationMode_removeWindowListeners() {
+      window.removeEventListener('mousemove', this.showControlsBind);
+      window.removeEventListener('mousedown', this.mouseDownBind);
+      window.removeEventListener('wheel', this.mouseWheelBind);
+      window.removeEventListener('keydown', this.resetMouseScrollStateBind);
+      window.removeEventListener('contextmenu', this.contextMenuBind);
+      window.removeEventListener('touchstart', this.touchSwipeBind);
+      window.removeEventListener('touchmove', this.touchSwipeBind);
+      window.removeEventListener('touchend', this.touchSwipeBind);
+
+      delete this.showControlsBind;
+      delete this.mouseDownBind;
+      delete this.mouseWheelBind;
+      delete this.resetMouseScrollStateBind;
+      delete this.contextMenuBind;
+      delete this.touchSwipeBind;
+    },
+
+    /**
+     * @private
+     */
+    _fullscreenChange: function PDFPresentationMode_fullscreenChange() {
+      if (this.isFullscreen) {
+        this._enter();
+      } else {
+        this._exit();
+      }
+    },
+
+    /**
+     * @private
+     */
+    _addFullscreenChangeListeners:
+        function PDFPresentationMode_addFullscreenChangeListeners() {
+      this.fullscreenChangeBind = this._fullscreenChange.bind(this);
+
+      window.addEventListener('fullscreenchange', this.fullscreenChangeBind);
+      window.addEventListener('mozfullscreenchange', this.fullscreenChangeBind);
+    },
+
+    /**
+     * @private
+     */
+    _removeFullscreenChangeListeners:
+        function PDFPresentationMode_removeFullscreenChangeListeners() {
+      window.removeEventListener('fullscreenchange', this.fullscreenChangeBind);
+      window.removeEventListener('mozfullscreenchange',
+                                 this.fullscreenChangeBind);
+
+      delete this.fullscreenChangeBind;
+    }
+  };
+
+  return PDFPresentationMode;
+})();
+
+exports.PDFPresentationMode = PDFPresentationMode;
+}));
+
+
+(function (root, factory) {
+  {
     factory((root.pdfjsWebPDFThumbnailView = {}), root.pdfjsWebUIUtils,
       root.pdfjsWebPDFRenderingQueue);
   }
 }(this, function (exports, uiUtils, pdfRenderingQueue) {
 
 var mozL10n = uiUtils.mozL10n;
 var getOutputScale = uiUtils.getOutputScale;
 var RenderingStates = pdfRenderingQueue.RenderingStates;
@@ -5802,16 +5924,18 @@ exports.PDFThumbnailViewer = PDFThumbnai
 
 (function (root, factory) {
   {
     factory((root.pdfjsWebTextLayerBuilder = {}), root.pdfjsWebDOMEvents,
       root.pdfjsWebPDFJS);
   }
 }(this, function (exports, domEvents, pdfjsLib) {
 
+var EXPAND_DIVS_TIMEOUT = 300; // ms
+
 /**
  * @typedef {Object} TextLayerBuilderOptions
  * @property {HTMLDivElement} textLayerDiv - The text layer container.
  * @property {EventBus} eventBus - The application event bus.
  * @property {number} pageIndex - The page index.
  * @property {PageViewport} viewport - The viewport of the text layer.
  * @property {PDFFindController} findController
  * @property {boolean} enhanceTextSelection - Option to turn on improved
@@ -6095,16 +6219,17 @@ var TextLayerBuilder = (function TextLay
     /**
      * Fixes text selection: adds additional div where mouse was clicked.
      * This reduces flickering of the content if mouse slowly dragged down/up.
      * @private
      */
     _bindMouse: function TextLayerBuilder_bindMouse() {
       var div = this.textLayerDiv;
       var self = this;
+      var expandDivsTimer = null;
       div.addEventListener('mousedown', function (e) {
         if (self.enhanceTextSelection && self.textLayerRenderTask) {
           self.textLayerRenderTask.expandTextDivs(true);
           return;
         }
         var end = div.querySelector('.endOfContent');
         if (!end) {
           return;
@@ -7175,16 +7300,17 @@ var RenderingStates = pdfRenderingQueueL
 var PDFRenderingQueue = pdfRenderingQueueLib.PDFRenderingQueue;
 var PDFLinkService = pdfLinkServiceLib.PDFLinkService;
 var PDFOutlineViewer = pdfOutlineViewerLib.PDFOutlineViewer;
 var OverlayManager = overlayManagerLib.OverlayManager;
 var PDFAttachmentViewer = pdfAttachmentViewerLib.PDFAttachmentViewer;
 var PDFFindController = pdfFindControllerLib.PDFFindController;
 var PDFFindBar = pdfFindBarLib.PDFFindBar;
 var getGlobalEventBus = domEventsLib.getGlobalEventBus;
+var normalizeWheelEventDelta = uiUtilsLib.normalizeWheelEventDelta;
 
 var DEFAULT_SCALE_DELTA = 1.1;
 var MIN_SCALE = 0.25;
 var MAX_SCALE = 10.0;
 var SCALE_SELECT_CONTAINER_PADDING = 8;
 var SCALE_SELECT_PADDING = 22;
 var PAGE_NUMBER_LOADING_INDICATOR = 'visiblePageIsLoading';
 var DISABLE_AUTO_FETCH_LOADING_BAR_TIMEOUT = 5000;
@@ -8207,26 +8333,16 @@ var PDFViewerApplication = {
   requestPresentationMode: function pdfViewRequestPresentationMode() {
     if (!this.pdfPresentationMode) {
       return;
     }
     this.pdfPresentationMode.request();
   },
 
   /**
-   * @param {number} delta - The delta value from the mouse event.
-   */
-  scrollPresentationMode: function pdfViewScrollPresentationMode(delta) {
-    if (!this.pdfPresentationMode) {
-      return;
-    }
-    this.pdfPresentationMode.mouseScroll(delta);
-  },
-
-  /**
    * @typedef UpdateUIToolbarParameters
    * @property {number} pageNumber
    * @property {string} scaleValue
    * @property {number} scale
    * @property {boolean} resetNumPages
    */
 
   /**
@@ -8663,16 +8779,19 @@ function webViewerUpdateViewarea(e) {
   if (currentPage.renderingState === RenderingStates.FINISHED) {
     pageNumberInput.classList.remove(PAGE_NUMBER_LOADING_INDICATOR);
   } else {
     pageNumberInput.classList.add(PAGE_NUMBER_LOADING_INDICATOR);
   }
 }
 
 window.addEventListener('resize', function webViewerResize(evt) {
+  if (!PDFViewerApplication.eventBus) {
+    return;
+  }
   PDFViewerApplication.eventBus.dispatch('resize');
 });
 
 function webViewerResize() {
   if (PDFViewerApplication.initialized) {
     var currentScaleValue = PDFViewerApplication.pdfViewer.currentScaleValue;
     if (currentScaleValue === 'auto' ||
         currentScaleValue === 'page-fit' ||
@@ -8818,42 +8937,45 @@ function webViewerPageChanging(e) {
     if (pageView.stats) {
       Stats.add(page, pageView.stats);
     }
   }
 }
 
 var zoomDisabled = false, zoomDisabledTimeout;
 function handleMouseWheel(evt) {
-  var MOUSE_WHEEL_DELTA_FACTOR = 40;
-  var ticks = (evt.type === 'DOMMouseScroll') ? -evt.detail :
-              evt.wheelDelta / MOUSE_WHEEL_DELTA_FACTOR;
-  var direction = (ticks < 0) ? 'zoomOut' : 'zoomIn';
-
   var pdfViewer = PDFViewerApplication.pdfViewer;
   if (pdfViewer.isInPresentationMode) {
-    evt.preventDefault();
-    PDFViewerApplication.scrollPresentationMode(ticks *
-                                                MOUSE_WHEEL_DELTA_FACTOR);
-  } else if (evt.ctrlKey || evt.metaKey) {
+    return;
+  }
+
+  if (evt.ctrlKey || evt.metaKey) {
     var support = PDFViewerApplication.supportedMouseWheelZoomModifierKeys;
     if ((evt.ctrlKey && !support.ctrlKey) ||
         (evt.metaKey && !support.metaKey)) {
       return;
     }
     // Only zoom the pages, not the entire viewer.
     evt.preventDefault();
     // NOTE: this check must be placed *after* preventDefault.
     if (zoomDisabled) {
       return;
     }
 
     var previousScale = pdfViewer.currentScale;
 
-    PDFViewerApplication[direction](Math.abs(ticks));
+    var delta = normalizeWheelEventDelta(evt);
+
+    var MOUSE_WHEEL_DELTA_PER_PAGE_SCALE = 3.0;
+    var ticks = delta * MOUSE_WHEEL_DELTA_PER_PAGE_SCALE;
+    if (ticks < 0) {
+      PDFViewerApplication.zoomOut(-ticks);
+    } else {
+      PDFViewerApplication.zoomIn(ticks);
+    }
 
     var currentScale = pdfViewer.currentScale;
     if (previousScale !== currentScale) {
       // After scaling the page via zoomIn/zoomOut, the position of the upper-
       // left corner is restored. When the mouse wheel is used, the position
       // under the cursor should be restored instead.
       var scaleCorrectionFactor = currentScale / previousScale - 1;
       var rect = pdfViewer.container.getBoundingClientRect();
@@ -8866,18 +8988,17 @@ function handleMouseWheel(evt) {
     zoomDisabled = true;
     clearTimeout(zoomDisabledTimeout);
     zoomDisabledTimeout = setTimeout(function () {
       zoomDisabled = false;
     }, 1000);
   }
 }
 
-window.addEventListener('DOMMouseScroll', handleMouseWheel);
-window.addEventListener('mousewheel', handleMouseWheel);
+window.addEventListener('wheel', handleMouseWheel);
 
 window.addEventListener('click', function click(evt) {
   if (!PDFViewerApplication.secondaryToolbar.isOpen) {
     return;
   }
   var appConfig = PDFViewerApplication.appConfig;
   if (PDFViewerApplication.pdfViewer.containsElement(evt.target) ||
       (appConfig.toolbar.container.contains(evt.target) &&
--- a/devtools/client/animationinspector/test/browser_animation_spacebar_toggles_node_animations.js
+++ b/devtools/client/animationinspector/test/browser_animation_spacebar_toggles_node_animations.js
@@ -5,16 +5,19 @@
 "use strict";
 
 // Test that the spacebar key press toggles the play/resume button state.
 // This test doesn't need to test if animations actually pause/resume
 // because there's an other test that does this.
 // There are animations in the test page and since, by default, the <body> node
 // is selected, animations will be displayed in the timeline, so the timeline
 // play/resume button will be displayed
+
+requestLongerTimeout(2);
+
 add_task(function* () {
   requestLongerTimeout(2);
 
   yield addTab(URL_ROOT + "doc_simple_animation.html");
   let {panel, window} = yield openAnimationInspector();
   let {playTimelineButtonEl} = panel;
 
   // ensure the focus is on the animation panel
--- a/devtools/client/debugger/new/bundle.js
+++ b/devtools/client/debugger/new/bundle.js
@@ -1,9 +1,9 @@
-// Generated from: 7c393c99dd82e9b181dab64ff474ee6ca9dc1c3f Revert "Add search input"
+// Generated from: bea6f2d2e0efef114265f177def09806e7f69784 Merge pull request #843 from jlongster/fix-css-var
 
 var Debugger =
 /******/ (function(modules) { // webpackBootstrap
 /******/ 	// The module cache
 /******/ 	var installedModules = {};
 /******/
 /******/ 	// The require function
 /******/ 	function __webpack_require__(moduleId) {
@@ -93,32 +93,32 @@ var Debugger =
 	
 	var _require5 = __webpack_require__(96);
 	
 	var getClient = _require5.getClient;
 	var connectClients = _require5.connectClients;
 	var startDebugging = _require5.startDebugging;
 	
 	var firefox = __webpack_require__(98);
-	var configureStore = __webpack_require__(180);
+	var configureStore = __webpack_require__(178);
 	var reducers = __webpack_require__(188);
 	var selectors = __webpack_require__(199);
 	
-	var Tabs = __webpack_require__(206);
-	var App = __webpack_require__(212);
+	var Tabs = __webpack_require__(200);
+	var App = __webpack_require__(206);
 	
 	var createStore = configureStore({
 	  log: getValue("logging.actions"),
 	  makeThunkArgs: (args, state) => {
 	    return Object.assign({}, args, { client: getClient(state) });
 	  }
 	});
 	
 	var store = createStore(combineReducers(reducers));
-	var actions = bindActionCreators(__webpack_require__(214), store.dispatch);
+	var actions = bindActionCreators(__webpack_require__(209), store.dispatch);
 	
 	if (isDevelopment()) {
 	  AppConstants.DEBUG_JS_MODULES = true;
 	  injectGlobals({ store });
 	}
 	
 	// Expose the bound actions so external things can do things like
 	// selecting a source.
@@ -164,17 +164,17 @@ var Debugger =
 	if (connTarget) {
 	  startDebugging(connTarget, actions).then(tabs => {
 	    actions.newTabs(tabs);
 	    actions.selectTab({ id: connTarget.param });
 	    renderRoot(App);
 	  });
 	} else if (isFirefoxPanel()) {
 	  (function () {
-	    var sourceMap = __webpack_require__(216);
+	    var sourceMap = __webpack_require__(211);
 	
 	    module.exports = {
 	      bootstrap: _ref => {
 	        var threadClient = _ref.threadClient;
 	        var tabTarget = _ref.tabTarget;
 	
 	        firefox.setThreadClient(threadClient);
 	        firefox.setTabTarget(tabTarget);
@@ -188,19 +188,17 @@ var Debugger =
 	      store: store,
 	      actions: actions,
 	      selectors: selectors,
 	      client: firefox.clientCommands
 	    };
 	  })();
 	} else {
 	  renderRoot(Tabs);
-	  connectClients().then(tabs => {
-	    actions.newTabs(tabs);
-	  });
+	  connectClients(tabs => actions.newTabs(tabs));
 	}
 
 /***/ },
 /* 2 */
 /***/ function(module, exports, __webpack_require__) {
 
 	'use strict';
 	
@@ -1140,17 +1138,17 @@ var Debugger =
 	Provider.childContextTypes = {
 	  store: _storeShape2["default"].isRequired
 	};
 
 /***/ },
 /* 17 */
 /***/ function(module, exports) {
 
-	module.exports = devtoolsRequire('devtools/client/shared/vendor/react');
+	module.exports = devtoolsRequire("devtools/client/shared/vendor/react");
 
 /***/ },
 /* 18 */
 /***/ function(module, exports, __webpack_require__) {
 
 	'use strict';
 	
 	exports.__esModule = true;
@@ -1760,17 +1758,17 @@ var Debugger =
 	
 	module.exports = __webpack_require__(26);
 
 
 /***/ },
 /* 26 */
 /***/ function(module, exports) {
 
-	module.exports = devtoolsRequire('devtools/client/shared/vendor/react-dom');
+	module.exports = devtoolsRequire("devtools/client/shared/vendor/react-dom");
 
 /***/ },
 /* 27 */
 /***/ 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/. */
@@ -6784,43 +6782,104 @@ var Debugger =
 	};
 	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(34).setImmediate, __webpack_require__(34).clearImmediate))
 
 /***/ },
 /* 35 */
 /***/ function(module, exports) {
 
 	// shim for using process in browser
-	
 	var process = module.exports = {};
 	
 	// cached from whatever global is present so that test runners that stub it
 	// don't break things.  But we need to wrap it in a try catch in case it is
 	// wrapped in strict mode code which doesn't define any globals.  It's inside a
 	// function because try/catches deoptimize in certain engines.
 	
 	var cachedSetTimeout;
 	var cachedClearTimeout;
 	
+	function defaultSetTimout() {
+	    throw new Error('setTimeout has not been defined');
+	}
+	function defaultClearTimeout () {
+	    throw new Error('clearTimeout has not been defined');
+	}
 	(function () {
-	  try {
-	    cachedSetTimeout = setTimeout;
-	  } catch (e) {
-	    cachedSetTimeout = function () {
-	      throw new Error('setTimeout is not defined');
-	    }
-	  }
-	  try {
-	    cachedClearTimeout = clearTimeout;
-	  } catch (e) {
-	    cachedClearTimeout = function () {
-	      throw new Error('clearTimeout is not defined');
-	    }
-	  }
+	    try {
+	        if (typeof setTimeout === 'function') {
+	            cachedSetTimeout = setTimeout;
+	        } else {
+	            cachedSetTimeout = defaultSetTimout;
+	        }
+	    } catch (e) {
+	        cachedSetTimeout = defaultSetTimout;
+	    }
+	    try {
+	        if (typeof clearTimeout === 'function') {
+	            cachedClearTimeout = clearTimeout;
+	        } else {
+	            cachedClearTimeout = defaultClearTimeout;
+	        }
+	    } catch (e) {
+	        cachedClearTimeout = defaultClearTimeout;
+	    }
 	} ())
+	function runTimeout(fun) {
+	    if (cachedSetTimeout === setTimeout) {
+	        //normal enviroments in sane situations
+	        return setTimeout(fun, 0);
+	    }
+	    // if setTimeout wasn't available but was latter defined
+	    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
+	        cachedSetTimeout = setTimeout;
+	        return setTimeout(fun, 0);
+	    }
+	    try {
+	        // when when somebody has screwed with setTimeout but no I.E. maddness
+	        return cachedSetTimeout(fun, 0);
+	    } catch(e){
+	        try {
+	            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+	            return cachedSetTimeout.call(null, fun, 0);
+	        } catch(e){
+	            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
+	            return cachedSetTimeout.call(this, fun, 0);
+	        }
+	    }
+	
+	
+	}
+	function runClearTimeout(marker) {
+	    if (cachedClearTimeout === clearTimeout) {
+	        //normal enviroments in sane situations
+	        return clearTimeout(marker);
+	    }
+	    // if clearTimeout wasn't available but was latter defined
+	    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
+	        cachedClearTimeout = clearTimeout;
+	        return clearTimeout(marker);
+	    }
+	    try {
+	        // when when somebody has screwed with setTimeout but no I.E. maddness
+	        return cachedClearTimeout(marker);
+	    } catch (e){
+	        try {
+	            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
+	            return cachedClearTimeout.call(null, marker);
+	        } catch (e){
+	            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
+	            // Some versions of I.E. have different rules for clearTimeout vs setTimeout
+	            return cachedClearTimeout.call(this, marker);
+	        }
+	    }
+	
+	
+	
+	}
 	var queue = [];
 	var draining = false;
 	var currentQueue;
 	var queueIndex = -1;
 	
 	function cleanUpNextTick() {
 	    if (!draining || !currentQueue) {
 	        return;
@@ -6835,46 +6894,46 @@ var Debugger =
 	        drainQueue();
 	    }
 	}
 	
 	function drainQueue() {
 	    if (draining) {
 	        return;
 	    }
-	    var timeout = cachedSetTimeout(cleanUpNextTick);
+	    var timeout = runTimeout(cleanUpNextTick);
 	    draining = true;
 	
 	    var len = queue.length;
 	    while(len) {
 	        currentQueue = queue;
 	        queue = [];
 	        while (++queueIndex < len) {
 	            if (currentQueue) {
 	                currentQueue[queueIndex].run();
 	            }
 	        }
 	        queueIndex = -1;
 	        len = queue.length;
 	    }
 	    currentQueue = null;
 	    draining = false;
-	    cachedClearTimeout(timeout);
+	    runClearTimeout(timeout);
 	}
 	
 	process.nextTick = function (fun) {
 	    var args = new Array(arguments.length - 1);
 	    if (arguments.length > 1) {
 	        for (var i = 1; i < arguments.length; i++) {
 	            args[i - 1] = arguments[i];
 	        }
 	    }
 	    queue.push(new Item(fun, args));
 	    if (queue.length === 1 && !draining) {
-	        cachedSetTimeout(drainQueue, 0);
+	        runTimeout(drainQueue);
 	    }
 	};
 	
 	// v8 likes predictible objects
 	function Item(fun, array) {
 	    this.fun = fun;
 	    this.array = array;
 	}
@@ -8673,17 +8732,17 @@ var Debugger =
 	  getConfig,
 	  setConfig
 	};
 
 /***/ },
 /* 48 */
 /***/ function(module, exports) {
 
-	module.exports = devtoolsRequire('devtools/shared/flags');
+	module.exports = devtoolsRequire("devtools/shared/flags");
 
 /***/ },
 /* 49 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var baseGet = __webpack_require__(50);
 	
 	/**
@@ -10162,18 +10221,16 @@ var Debugger =
 	}
 	
 	module.exports = injectDebuggee;
 
 /***/ },
 /* 96 */
 /***/ function(module, exports, __webpack_require__) {
 
-	var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
-	
 	var _require = __webpack_require__(97);
 	
 	var Task = _require.Task;
 	
 	var firefox = __webpack_require__(98);
 	var chrome = __webpack_require__(173);
 	
 	var _require2 = __webpack_require__(45);
@@ -10215,25 +10272,19 @@ var Debugger =
 	
 	    clientType = targetEnv === firefox ? "firefox" : "chrome";
 	    debugGlobal("client", targetEnv.clientCommands);
 	
 	    return tabs;
 	  });
 	}
 	
-	function connectClients() {
-	  return Promise.all([firefox.connectClient(), chrome.connectClient()]).then(results => {
-	    var _results = _slicedToArray(results, 2);
-	
-	    var firefoxTabs = _results[0];
-	    var chromeTabs = _results[1];
-	
-	    return firefoxTabs.concat(chromeTabs).filter(i => i);
-	  });
+	function connectClients(onConnect) {
+	  firefox.connectClient().then(onConnect);
+	  chrome.connectClient().then(onConnect);
 	}
 	
 	module.exports = {
 	  getClient,
 	  connectClients,
 	  startDebugging
 	};
 
@@ -10379,17 +10430,17 @@ var Debugger =
 	  debuggerClient = new DebuggerClient(transport);
 	
 	  debuggerClient.connect().then(() => {
 	    return debuggerClient.listTabs().then(response => {
 	      deferred.resolve(createTabs(response.tabs));
 	    });
 	  }).catch(err => {
 	    console.log(err);
-	    deferred.reject();
+	    deferred.resolve([]);
 	  });
 	
 	  return deferred.promise;
 	}
 	
 	function connectTab(tab) {
 	  return new Promise((resolve, reject) => {
 	    window.addEventListener("beforeunload", () => {
@@ -13379,30 +13430,31 @@ var Debugger =
 	   * Request to set a breakpoint in the specified location.
 	   *
 	   * @param object aLocation
 	   *        The location and condition of the breakpoint in
 	   *        the form of { line[, column, condition] }.
 	   * @param function aOnResponse
 	   *        Called with the thread's response.
 	   */
-	  setBreakpoint: function ({ line, column, condition }, aOnResponse = noop) {
+	  setBreakpoint: function ({ line, column, condition, noSliding }, aOnResponse = noop) {
 	    // A helper function that sets the breakpoint.
 	    let doSetBreakpoint = aCallback => {
 	      let root = this._client.mainRoot;
 	      let location = {
 	        line: line,
 	        column: column
 	      };
 	
 	      let packet = {
 	        to: this.actor,
 	        type: "setBreakpoint",
 	        location: location,
-	        condition: condition
+	        condition: condition,
+	        noSliding: noSliding
 	      };
 	
 	      // Backwards compatibility: send the breakpoint request to the
 	      // thread if the server doesn't support Debugger.Source actors.
 	      if (!root.traits.debuggerSourceActors) {
 	        packet.to = this._activeThread.actor;
 	        packet.location.url = this.url;
 	      }
@@ -19740,23 +19792,24 @@ var Debugger =
 	  return threadClient.breakOnNext();
 	}
 	
 	function sourceContents(sourceId) {
 	  var sourceClient = threadClient.source({ actor: sourceId });
 	  return sourceClient.source();
 	}
 	
-	function setBreakpoint(location, condition) {
+	function setBreakpoint(location, condition, noSliding) {
 	  var sourceClient = threadClient.source({ actor: location.sourceId });
 	
 	  return sourceClient.setBreakpoint({
 	    line: location.line,
 	    column: location.column,
-	    condition: condition
+	    condition,
+	    noSliding
 	  }).then(_ref => {
 	    var _ref2 = _slicedToArray(_ref, 2);
 	
 	    var res = _ref2[0];
 	    var bpClient = _ref2[1];
 	
 	    bpClients[bpClient.actor] = bpClient;
 	
@@ -19950,22 +20003,17 @@ var Debugger =
 	      line: frame.where.line,
 	      column: frame.where.column
 	    }),
 	    this: frame.this,
 	    scope: frame.environment
 	  });
 	}
 	
-	var evalIndex = 1;
 	function createSource(source) {
-	  if (!source.url) {
-	    source.url = `SOURCE${ evalIndex++ }`;
-	  }
-	
 	  return Source({
 	    id: source.actor,
 	    url: source.url,
 	    isPrettyPrinted: false,
 	    sourceMapURL: source.sourceMapURL
 	  });
 	}
 	
@@ -19991,22 +20039,22 @@ var Debugger =
 	
 	var isEnabled = _require3.isEnabled;
 	var getValue = _require3.getValue;
 	
 	var _require4 = __webpack_require__(175);
 	
 	var networkRequest = _require4.networkRequest;
 	
-	var _require5 = __webpack_require__(178);
+	var _require5 = __webpack_require__(176);
 	
 	var setupCommands = _require5.setupCommands;
 	var clientCommands = _require5.clientCommands;
 	
-	var _require6 = __webpack_require__(179);
+	var _require6 = __webpack_require__(177);
 	
 	var setupEvents = _require6.setupEvents;
 	var clientEvents = _require6.clientEvents;
 	var pageEvents = _require6.pageEvents;
 	
 	// TODO: figure out a way to avoid patching native prototypes.
 	// Unfortunately the Chrome client requires it to work.
 	
@@ -20036,18 +20084,18 @@ var Debugger =
 	  var deferred = defer();
 	
 	  if (!getValue("chrome.debug")) {
 	    return deferred.resolve(createTabs([]));
 	  }
 	
 	  var webSocketPort = getValue("chrome.webSocketPort");
 	  var url = `http://localhost:${ webSocketPort }/json/list`;
-	  networkRequest(url).then(body => {
-	    deferred.resolve(createTabs(body));
+	  networkRequest(url).then(res => {
+	    deferred.resolve(createTabs(JSON.parse(res.content)));
 	  }).catch(err => {
 	    console.log(err);
 	    deferred.reject();
 	  });
 	
 	  return deferred.promise;
 	}
 	
@@ -20093,43 +20141,534 @@ var Debugger =
 /***/ },
 /* 174 */
 /***/ function(module, exports) {
 
 	module.exports = {};
 
 /***/ },
 /* 175 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var _require = __webpack_require__(176);
-	
-	var log = _require.log;
-	
-	
-	function networkRequest(url) {
-	  return Promise.race([fetch(`/get?url=${ url }`).then(res => {
-	    if (res.status >= 200 && res.status < 300) {
-	      return res.json();
-	    }
-	    log(`failed to request ${ url }`);
-	    return Promise.resolve([]);
-	  }), new Promise((resolve, reject) => {
-	    setTimeout(() => reject(new Error("Connect timeout error")), 6000);
-	  })]);
-	}
-	
-	module.exports = {
-	  networkRequest
-	};
+/***/ function(module, exports) {
+
+	module.exports = devtoolsRequire("devtools/shared/DevToolsUtils")["fetch"];
 
 /***/ },
 /* 176 */
 /***/ function(module, exports, __webpack_require__) {
 
+	var _require = __webpack_require__(114);
+	
+	var BreakpointResult = _require.BreakpointResult;
+	var Location = _require.Location;
+	
+	
+	var debuggerAgent = void 0;
+	var runtimeAgent = void 0;
+	var pageAgent = void 0;
+	
+	function setupCommands(_ref) {
+	  var agents = _ref.agents;
+	
+	  debuggerAgent = agents.Debugger;
+	  runtimeAgent = agents.Runtime;
+	  pageAgent = agents.Page;
+	}
+	
+	function resume() {
+	  return debuggerAgent.resume();
+	}
+	
+	function stepIn() {
+	  return debuggerAgent.stepInto();
+	}
+	
+	function stepOver() {
+	  return debuggerAgent.stepOver();
+	}
+	
+	function stepOut() {
+	  return debuggerAgent.stepOut();
+	}
+	
+	function pauseOnExceptions(toggle) {
+	  var state = toggle ? "uncaught" : "none";
+	  return debuggerAgent.setPauseOnExceptions(state);
+	}
+	
+	function breakOnNext() {
+	  return debuggerAgent.pause();
+	}
+	
+	function sourceContents(sourceId) {
+	  return debuggerAgent.getScriptSource(sourceId, (err, contents) => ({
+	    source: contents,
+	    contentType: null
+	  }));
+	}
+	
+	function setBreakpoint(location, condition) {
+	  return new Promise((resolve, reject) => {
+	    return debuggerAgent.setBreakpoint({
+	      scriptId: location.sourceId,
+	      lineNumber: location.line - 1,
+	      columnNumber: location.column
+	    }, (err, breakpointId, actualLocation) => {
+	      if (err) {
+	        reject(err);
+	        return;
+	      }
+	
+	      actualLocation = actualLocation ? {
+	        sourceId: actualLocation.scriptId,
+	        line: actualLocation.lineNumber + 1,
+	        column: actualLocation.columnNumber
+	      } : location;
+	
+	      resolve(BreakpointResult({
+	        id: breakpointId,
+	        actualLocation: Location(actualLocation)
+	      }));
+	    });
+	  });
+	}
+	
+	function removeBreakpoint(breakpointId) {
+	  // TODO: resolve promise when request is completed.
+	  return new Promise((resolve, reject) => {
+	    resolve(debuggerAgent.removeBreakpoint(breakpointId));
+	  });
+	}
+	
+	function evaluate(script) {
+	  return runtimeAgent.evaluate(script, (_, result) => {
+	    return result;
+	  });
+	}
+	
+	function debuggeeCommand(script) {
+	  evaluate(script);
+	  return Promise.resolve();
+	}
+	
+	function navigate(url) {
+	  return pageAgent.navigate(url, (_, result) => {
+	    return result;
+	  });
+	}
+	
+	var clientCommands = {
+	  resume,
+	  stepIn,
+	  stepOut,
+	  stepOver,
+	  pauseOnExceptions,
+	  breakOnNext,
+	  sourceContents,
+	  setBreakpoint,
+	  removeBreakpoint,
+	  evaluate,
+	  debuggeeCommand,
+	  navigate
+	};
+	
+	module.exports = {
+	  setupCommands,
+	  clientCommands
+	};
+
+/***/ },
+/* 177 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var paused = (() => {
+	  var _ref = _asyncToGenerator(function* (callFrames, reason, data, hitBreakpoints, asyncStackTrace) {
+	    var frames = callFrames.map(function (frame) {
+	      return Frame({
+	        id: frame.callFrameId,
+	        displayName: frame.functionName,
+	        location: Location({
+	          sourceId: frame.location.scriptId,
+	          line: frame.location.lineNumber + 1,
+	          column: frame.location.columnNumber
+	        })
+	      });
+	    });
+	
+	    var frame = frames[0];
+	    var why = Object.assign({}, {
+	      type: reason
+	    }, data);
+	
+	    pageAgent.setOverlayMessage("Paused in debugger.html");
+	
+	    yield actions.paused({ frame, why, frames });
+	  });
+	
+	  return function paused(_x, _x2, _x3, _x4, _x5) {
+	    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) { return step("next", value); }, function (err) { return step("throw", err); }); } } return step("next"); }); }; }
+	
+	var _require = __webpack_require__(114);
+	
+	var Source = _require.Source;
+	var Location = _require.Location;
+	var Frame = _require.Frame;
+	
+	
+	var actions = void 0;
+	var pageAgent = void 0;
+	
+	function setupEvents(dependencies) {
+	  actions = dependencies.actions;
+	  pageAgent = dependencies.agents.Page;
+	}
+	
+	// Debugger Events
+	function scriptParsed(scriptId, url, startLine, startColumn, endLine, endColumn, executionContextId, hash, isContentScript, isInternalScript, isLiveEdit, sourceMapURL, hasSourceURL, deprecatedCommentWasUsed) {
+	  if (isContentScript) {
+	    return;
+	  }
+	
+	  actions.newSource(Source({
+	    id: scriptId,
+	    url,
+	    sourceMapURL,
+	    isPrettyPrinted: false
+	  }));
+	}
+	
+	function scriptFailedToParse() {}
+	
+	function resumed() {
+	  pageAgent.setOverlayMessage(undefined);
+	  actions.resumed();
+	}
+	
+	function globalObjectCleared() {}
+	
+	// Page Events
+	function frameNavigated(frame) {
+	  actions.navigate();
+	}
+	
+	function frameStartedLoading() {
+	  actions.willNavigate();
+	}
+	
+	function domContentEventFired() {}
+	
+	function loadEventFired() {}
+	
+	function frameStoppedLoading() {}
+	
+	var clientEvents = {
+	  scriptParsed,
+	  scriptFailedToParse,
+	  paused,
+	  resumed,
+	  globalObjectCleared
+	};
+	
+	var pageEvents = {
+	  frameNavigated,
+	  frameStartedLoading,
+	  domContentEventFired,
+	  loadEventFired,
+	  frameStoppedLoading
+	};
+	
+	module.exports = {
+	  setupEvents,
+	  pageEvents,
+	  clientEvents
+	};
+
+/***/ },
+/* 178 */
+/***/ 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/. */
+	/* global window */
+	
+	var _require = __webpack_require__(2);
+	
+	var createStore = _require.createStore;
+	var applyMiddleware = _require.applyMiddleware;
+	
+	var _require2 = __webpack_require__(179);
+	
+	var waitUntilService = _require2.waitUntilService;
+	
+	var _require3 = __webpack_require__(180);
+	
+	var log = _require3.log;
+	
+	var _require4 = __webpack_require__(181);
+	
+	var history = _require4.history;
+	
+	var _require5 = __webpack_require__(182);
+	
+	var promise = _require5.promise;
+	
+	var _require6 = __webpack_require__(187);
+	
+	var thunk = _require6.thunk;
+	
+	
+	/**
+	 * This creates a dispatcher with all the standard middleware in place
+	 * that all code requires. It can also be optionally configured in
+	 * various ways, such as logging and recording.
+	 *
+	 * @param {object} opts:
+	 *        - log: log all dispatched actions to console
+	 *        - history: an array to store every action in. Should only be
+	 *                   used in tests.
+	 *        - middleware: array of middleware to be included in the redux store
+	 */
+	var configureStore = function () {
+	  var opts = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
+	
+	  var middleware = [thunk(opts.makeThunkArgs), promise,
+	
+	  // Order is important: services must go last as they always
+	  // operate on "already transformed" actions. Actions going through
+	  // them shouldn't have any special fields like promises, they
+	  // should just be normal JSON objects.
+	  waitUntilService];
+	
+	  if (opts.history) {
+	    middleware.push(history(opts.history));
+	  }
+	
+	  if (opts.middleware) {
+	    opts.middleware.forEach(fn => middleware.push(fn));
+	  }
+	
+	  if (opts.log) {
+	    middleware.push(log);
+	  }
+	
+	  // Hook in the redux devtools browser extension if it exists
+	  var devtoolsExt = typeof window === "object" && window.devToolsExtension ? window.devToolsExtension() : f => f;
+	
+	  return applyMiddleware.apply(undefined, middleware)(devtoolsExt(createStore));
+	};
+	
+	module.exports = configureStore;
+
+/***/ },
+/* 179 */
+/***/ 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";
+	
+	/**
+	 * A middleware which acts like a service, because it is stateful
+	 * and "long-running" in the background. It provides the ability
+	 * for actions to install a function to be run once when a specific
+	 * condition is met by an action coming through the system. Think of
+	 * it as a thunk that blocks until the condition is met. Example:
+	 *
+	 * ```js
+	 * const services = { WAIT_UNTIL: require('wait-service').NAME };
+	 *
+	 * { type: services.WAIT_UNTIL,
+	 *   predicate: action => action.type === constants.ADD_ITEM,
+	 *   run: (dispatch, getState, action) => {
+	 *     // Do anything here. You only need to accept the arguments
+	 *     // if you need them. `action` is the action that satisfied
+	 *     // the predicate.
+	 *   }
+	 * }
+	 * ```
+	 */
+	const NAME = exports.NAME = "@@service/waitUntil";
+	
+	function waitUntilService({ dispatch, getState }) {
+	  let pending = [];
+	
+	  function checkPending(action) {
+	    let readyRequests = [];
+	    let stillPending = [];
+	
+	    // Find the pending requests whose predicates are satisfied with
+	    // this action. Wait to run the requests until after we update the
+	    // pending queue because the request handler may synchronously
+	    // dispatch again and run this service (that use case is
+	    // completely valid).
+	    for (let request of pending) {
+	      if (request.predicate(action)) {
+	        readyRequests.push(request);
+	      } else {
+	        stillPending.push(request);
+	      }
+	    }
+	
+	    pending = stillPending;
+	    for (let request of readyRequests) {
+	      request.run(dispatch, getState, action);
+	    }
+	  }
+	
+	  return next => action => {
+	    if (action.type === NAME) {
+	      pending.push(action);
+	      return null;
+	    }
+	    let result = next(action);
+	    checkPending(action);
+	    return result;
+	  };
+	}
+	exports.waitUntilService = waitUntilService;
+
+
+/***/ },
+/* 180 */
+/***/ function(module, exports) {
+
+	/**
+	 * A middleware that logs all actions coming through the system
+	 * to the console.
+	 */
+	function log(_ref) {
+	  var dispatch = _ref.dispatch;
+	  var getState = _ref.getState;
+	
+	  return next => action => {
+	    var actionText = JSON.stringify(action, null, 2);
+	    var truncatedActionText = actionText.slice(0, 1000) + "...";
+	    console.log(`[DISPATCH ${ action.type }]`, action, truncatedActionText);
+	    next(action);
+	  };
+	}
+	
+	exports.log = log;
+
+/***/ },
+/* 181 */
+/***/ 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/. */
+	
+	var _require = __webpack_require__(46);
+	
+	var isDevelopment = _require.isDevelopment;
+	
+	/**
+	 * A middleware that stores every action coming through the store in the passed
+	 * in logging object. Should only be used for tests, as it collects all
+	 * action information, which will cause memory bloat.
+	 */
+	
+	exports.history = function () {
+	  var log = arguments.length <= 0 || arguments[0] === undefined ? [] : arguments[0];
+	  return _ref => {
+	    var dispatch = _ref.dispatch;
+	    var getState = _ref.getState;
+	
+	    if (isDevelopment()) {
+	      console.warn("Using history middleware stores all actions in state for " + "testing and devtools is not currently running in test " + "mode. Be sure this is intentional.");
+	    }
+	    return next => action => {
+	      log.push(action);
+	      next(action);
+	    };
+	  };
+	};
+
+/***/ },
+/* 182 */
+/***/ 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/. */
+	
+	var defer = __webpack_require__(112);
+	
+	var _require = __webpack_require__(183);
+	
+	var entries = _require.entries;
+	var toObject = _require.toObject;
+	
+	var _require2 = __webpack_require__(185);
+	
+	var executeSoon = _require2.executeSoon;
+	
+	
+	var PROMISE = exports.PROMISE = "@@dispatch/promise";
+	var seqIdVal = 1;
+	
+	function seqIdGen() {
+	  return seqIdVal++;
+	}
+	
+	function promiseMiddleware(_ref) {
+	  var dispatch = _ref.dispatch;
+	  var getState = _ref.getState;
+	
+	  return next => action => {
+	    if (!(PROMISE in action)) {
+	      return next(action);
+	    }
+	
+	    var promiseInst = action[PROMISE];
+	    var seqId = seqIdGen().toString();
+	
+	    // Create a new action that doesn't have the promise field and has
+	    // the `seqId` field that represents the sequence id
+	    action = Object.assign(toObject(entries(action).filter(pair => pair[0] !== PROMISE)), { seqId });
+	
+	    dispatch(Object.assign({}, action, { status: "start" }));
+	
+	    // Return the promise so action creators can still compose if they
+	    // want to.
+	    var deferred = defer();
+	    promiseInst.then(value => {
+	      executeSoon(() => {
+	        dispatch(Object.assign({}, action, {
+	          status: "done",
+	          value: value
+	        }));
+	        deferred.resolve(value);
+	      });
+	    }, error => {
+	      executeSoon(() => {
+	        dispatch(Object.assign({}, action, {
+	          status: "error",
+	          error: error.message || error
+	        }));
+	        deferred.reject(error);
+	      });
+	    });
+	    return deferred.promise;
+	  };
+	}
+	
+	exports.promise = promiseMiddleware;
+
+/***/ },
+/* 183 */
+/***/ function(module, exports, __webpack_require__) {
+
 	var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
 	
 	var asyncMap = (() => {
 	  var _ref = _asyncToGenerator(function* (items, callback) {
 	    var newItems = [];
 	    for (var item of items) {
 	      item = yield callback(item);
 	      newItems.push(item);
@@ -20160,17 +20699,17 @@ var Debugger =
 	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) { return step("next", value); }, function (err) { return step("throw", err); }); } } return step("next"); }); }; }
 	
 	/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 	/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 	/* This Source Code Form is subject to the terms of the Mozilla Public
 	 * License, v. 2.0. If a copy of the MPL was not distributed with this
 	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 	
-	var co = __webpack_require__(177);
+	var co = __webpack_require__(184);
 	
 	var _require = __webpack_require__(46);
 	
 	var isDevelopment = _require.isDevelopment;
 	
 	var defer = __webpack_require__(112);
 	
 	function asPaused(client, func) {
@@ -20229,18 +20768,18 @@ var Debugger =
 	  }
 	  return str;
 	}
 	
 	function workerTask(worker, message) {
 	  var deferred = defer();
 	  worker.postMessage(message);
 	  worker.onmessage = function (result) {
-	    if (result.error) {
-	      deferred.reject(result.error);
+	    if (result.data && result.data.error) {
+	      deferred.reject(result.data.error);
 	    }
 	
 	    deferred.resolve(result.data);
 	  };
 	
 	  return deferred.promise;
 	}
 	
@@ -20362,17 +20901,17 @@ var Debugger =
 	  mapObject,
 	  compose,
 	  log,
 	  updateObj,
 	  throttle
 	};
 
 /***/ },
-/* 177 */
+/* 184 */
 /***/ function(module, exports) {
 
 	
 	/**
 	 * slice() reference.
 	 */
 	
 	var slice = Array.prototype.slice;
@@ -20605,560 +21144,49 @@ var Debugger =
 	 */
 	
 	function isObject(val) {
 	  return Object == val.constructor;
 	}
 
 
 /***/ },
-/* 178 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var _require = __webpack_require__(114);
-	
-	var BreakpointResult = _require.BreakpointResult;
-	var Location = _require.Location;
-	
-	
-	var debuggerAgent = void 0;
-	var runtimeAgent = void 0;
-	var pageAgent = void 0;
-	
-	function setupCommands(_ref) {
-	  var agents = _ref.agents;
-	
-	  debuggerAgent = agents.Debugger;
-	  runtimeAgent = agents.Runtime;
-	  pageAgent = agents.Page;
-	}
-	
-	function resume() {
-	  return debuggerAgent.resume();
-	}
-	
-	function stepIn() {
-	  return debuggerAgent.stepInto();
-	}
-	
-	function stepOver() {
-	  return debuggerAgent.stepOver();
-	}
-	
-	function stepOut() {
-	  return debuggerAgent.stepOut();
-	}
-	
-	function pauseOnExceptions(toggle) {
-	  var state = toggle ? "uncaught" : "none";
-	  return debuggerAgent.setPauseOnExceptions(state);
-	}
-	
-	function breakOnNext() {
-	  return debuggerAgent.pause();
-	}
-	
-	function sourceContents(sourceId) {
-	  return debuggerAgent.getScriptSource(sourceId, (err, contents) => ({
-	    source: contents,
-	    contentType: null
-	  }));
-	}
-	
-	function setBreakpoint(location, condition) {
-	  return new Promise((resolve, reject) => {
-	    return debuggerAgent.setBreakpoint({
-	      scriptId: location.sourceId,
-	      lineNumber: location.line - 1,
-	      columnNumber: location.column
-	    }, (err, breakpointId, actualLocation) => {
-	      if (err) {
-	        reject(err);
-	        return;
-	      }
-	
-	      actualLocation = actualLocation ? {
-	        sourceId: actualLocation.scriptId,
-	        line: actualLocation.lineNumber + 1,
-	        column: actualLocation.columnNumber
-	      } : location;
-	
-	      resolve(BreakpointResult({
-	        id: breakpointId,
-	        actualLocation: Location(actualLocation)
-	      }));
-	    });
-	  });
-	}
-	
-	function removeBreakpoint(breakpointId) {
-	  // TODO: resolve promise when request is completed.
-	  return new Promise((resolve, reject) => {
-	    resolve(debuggerAgent.removeBreakpoint(breakpointId));
-	  });
-	}
-	
-	function evaluate(script) {
-	  return runtimeAgent.evaluate(script, (_, result) => {
-	    return result;
-	  });
-	}
-	
-	function debuggeeCommand(script) {
-	  evaluate(script);
-	  return Promise.resolve();
-	}
-	
-	function navigate(url) {
-	  return pageAgent.navigate(url, (_, result) => {
-	    return result;
-	  });
-	}
-	
-	var clientCommands = {
-	  resume,
-	  stepIn,
-	  stepOut,
-	  stepOver,
-	  pauseOnExceptions,
-	  breakOnNext,
-	  sourceContents,
-	  setBreakpoint,
-	  removeBreakpoint,
-	  evaluate,
-	  debuggeeCommand,
-	  navigate
-	};
-	
-	module.exports = {
-	  setupCommands,
-	  clientCommands
-	};
-
-/***/ },
-/* 179 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var paused = (() => {
-	  var _ref = _asyncToGenerator(function* (callFrames, reason, data, hitBreakpoints, asyncStackTrace) {
-	    var frames = callFrames.map(function (frame) {
-	      return Frame({
-	        id: frame.callFrameId,
-	        displayName: frame.functionName,
-	        location: Location({
-	          sourceId: frame.location.scriptId,
-	          line: frame.location.lineNumber + 1,
-	          column: frame.location.columnNumber
-	        })
-	      });
-	    });
-	
-	    var frame = frames[0];
-	    var why = Object.assign({}, {
-	      type: reason
-	    }, data);
-	
-	    pageAgent.setOverlayMessage("Paused in debugger.html");
-	
-	    yield actions.paused({ frame, why, frames });
-	  });
-	
-	  return function paused(_x, _x2, _x3, _x4, _x5) {
-	    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) { return step("next", value); }, function (err) { return step("throw", err); }); } } return step("next"); }); }; }
-	
-	var _require = __webpack_require__(114);
-	
-	var Source = _require.Source;
-	var Location = _require.Location;
-	var Frame = _require.Frame;
-	
-	
-	var actions = void 0;
-	var pageAgent = void 0;
-	
-	function setupEvents(dependencies) {
-	  actions = dependencies.actions;
-	  pageAgent = dependencies.agents.Page;
-	}
-	
-	// Debugger Events
-	function scriptParsed(scriptId, url, startLine, startColumn, endLine, endColumn, executionContextId, hash, isContentScript, isInternalScript, isLiveEdit, sourceMapURL, hasSourceURL, deprecatedCommentWasUsed) {
-	  if (isContentScript) {
-	    return;
-	  }
-	
-	  actions.newSource(Source({
-	    id: scriptId,
-	    url,
-	    sourceMapURL,
-	    isPrettyPrinted: false
-	  }));
-	}
-	
-	function scriptFailedToParse() {}
-	
-	function resumed() {
-	  pageAgent.setOverlayMessage(undefined);
-	  actions.resumed();
-	}
-	
-	function globalObjectCleared() {}
-	
-	// Page Events
-	function frameNavigated(frame) {
-	  actions.navigate();
-	}
-	
-	function frameStartedLoading() {
-	  actions.willNavigate();
-	}
-	
-	function domContentEventFired() {}
-	
-	function loadEventFired() {}
-	
-	function frameStoppedLoading() {}
-	
-	var clientEvents = {
-	  scriptParsed,
-	  scriptFailedToParse,
-	  paused,
-	  resumed,
-	  globalObjectCleared
-	};
-	
-	var pageEvents = {
-	  frameNavigated,
-	  frameStartedLoading,
-	  domContentEventFired,
-	  loadEventFired,
-	  frameStoppedLoading
-	};
-	
-	module.exports = {
-	  setupEvents,
-	  pageEvents,
-	  clientEvents
-	};
-
-/***/ },
-/* 180 */
-/***/ 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/. */
-	/* global window */
-	
-	var _require = __webpack_require__(2);
-	
-	var createStore = _require.createStore;
-	var applyMiddleware = _require.applyMiddleware;
-	
-	var _require2 = __webpack_require__(181);
-	
-	var waitUntilService = _require2.waitUntilService;
-	
-	var _require3 = __webpack_require__(182);
-	
-	var log = _require3.log;
-	
-	var _require4 = __webpack_require__(183);
-	
-	var history = _require4.history;
-	
-	var _require5 = __webpack_require__(184);
-	
-	var promise = _require5.promise;
-	
-	var _require6 = __webpack_require__(187);
-	
-	var thunk = _require6.thunk;
-	
-	/**
-	 * This creates a dispatcher with all the standard middleware in place
-	 * that all code requires. It can also be optionally configured in
-	 * various ways, such as logging and recording.
-	 *
-	 * @param {object} opts:
-	 *        - log: log all dispatched actions to console
-	 *        - history: an array to store every action in. Should only be
-	 *                   used in tests.
-	 *        - middleware: array of middleware to be included in the redux store
-	 */
-	
-	var configureStore = function () {
-	  var opts = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
-	
-	  var middleware = [thunk(opts.makeThunkArgs), promise,
-	
-	  // Order is important: services must go last as they always
-	  // operate on "already transformed" actions. Actions going through
-	  // them shouldn't have any special fields like promises, they
-	  // should just be normal JSON objects.
-	  waitUntilService];
-	
-	  if (opts.history) {
-	    middleware.push(history(opts.history));
-	  }
-	
-	  if (opts.middleware) {
-	    opts.middleware.forEach(fn => middleware.push(fn));
-	  }
-	
-	  if (opts.log) {
-	    middleware.push(log);
-	  }
-	
-	  // Hook in the redux devtools browser extension if it exists
-	  var devtoolsExt = typeof window === "object" && window.devToolsExtension ? window.devToolsExtension() : f => f;
-	
-	  return applyMiddleware.apply(undefined, middleware)(devtoolsExt(createStore));
-	};
-	
-	module.exports = configureStore;
-
-/***/ },
-/* 181 */
-/***/ 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";
-	
-	/**
-	 * A middleware which acts like a service, because it is stateful
-	 * and "long-running" in the background. It provides the ability
-	 * for actions to install a function to be run once when a specific
-	 * condition is met by an action coming through the system. Think of
-	 * it as a thunk that blocks until the condition is met. Example:
-	 *
-	 * ```js
-	 * const services = { WAIT_UNTIL: require('wait-service').NAME };
-	 *
-	 * { type: services.WAIT_UNTIL,
-	 *   predicate: action => action.type === constants.ADD_ITEM,
-	 *   run: (dispatch, getState, action) => {
-	 *     // Do anything here. You only need to accept the arguments
-	 *     // if you need them. `action` is the action that satisfied
-	 *     // the predicate.
-	 *   }
-	 * }
-	 * ```
-	 */
-	const NAME = exports.NAME = "@@service/waitUntil";
-	
-	function waitUntilService({ dispatch, getState }) {
-	  let pending = [];
-	
-	  function checkPending(action) {
-	    let readyRequests = [];
-	    let stillPending = [];
-	
-	    // Find the pending requests whose predicates are satisfied with
-	    // this action. Wait to run the requests until after we update the
-	    // pending queue because the request handler may synchronously
-	    // dispatch again and run this service (that use case is
-	    // completely valid).
-	    for (let request of pending) {
-	      if (request.predicate(action)) {
-	        readyRequests.push(request);
-	      } else {
-	        stillPending.push(request);
-	      }
-	    }
-	
-	    pending = stillPending;
-	    for (let request of readyRequests) {
-	      request.run(dispatch, getState, action);
-	    }
-	  }
-	
-	  return next => action => {
-	    if (action.type === NAME) {
-	      pending.push(action);
-	      return null;
-	    }
-	    let result = next(action);
-	    checkPending(action);
-	    return result;
-	  };
-	}
-	exports.waitUntilService = waitUntilService;
-
-
-/***/ },
-/* 182 */
-/***/ function(module, exports) {
-
-	/**
-	 * A middleware that logs all actions coming through the system
-	 * to the console.
-	 */
-	function log(_ref) {
-	  var dispatch = _ref.dispatch;
-	  var getState = _ref.getState;
-	
-	  return next => action => {
-	    var actionText = JSON.stringify(action, null, 2);
-	    var truncatedActionText = actionText.slice(0, 1000) + "...";
-	    console.log(`[DISPATCH ${ action.type }]`, action, truncatedActionText);
-	    next(action);
-	  };
-	}
-	
-	exports.log = log;
-
-/***/ },
-/* 183 */
-/***/ 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/. */
-	
-	var _require = __webpack_require__(46);
-	
-	var isDevelopment = _require.isDevelopment;
-	
-	/**
-	 * A middleware that stores every action coming through the store in the passed
-	 * in logging object. Should only be used for tests, as it collects all
-	 * action information, which will cause memory bloat.
-	 */
-	
-	exports.history = function () {
-	  var log = arguments.length <= 0 || arguments[0] === undefined ? [] : arguments[0];
-	  return _ref => {
-	    var dispatch = _ref.dispatch;
-	    var getState = _ref.getState;
-	
-	    if (isDevelopment()) {
-	      console.warn("Using history middleware stores all actions in state for " + "testing and devtools is not currently running in test " + "mode. Be sure this is intentional.");
-	    }
-	    return next => action => {
-	      log.push(action);
-	      next(action);
-	    };
-	  };
-	};
-
-/***/ },
-/* 184 */
-/***/ 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/. */
-	
-	var uuidgen = __webpack_require__(185).uuid;
-	var defer = __webpack_require__(112);
-	
-	var _require = __webpack_require__(176);
-	
-	var entries = _require.entries;
-	var toObject = _require.toObject;
-	
-	var _require2 = __webpack_require__(186);
-	
-	var executeSoon = _require2.executeSoon;
-	
-	
-	var PROMISE = exports.PROMISE = "@@dispatch/promise";
-	
-	function promiseMiddleware(_ref) {
-	  var dispatch = _ref.dispatch;
-	  var getState = _ref.getState;
-	
-	  return next => action => {
-	    if (!(PROMISE in action)) {
-	      return next(action);
-	    }
-	
-	    var promiseInst = action[PROMISE];
-	    var seqId = uuidgen().toString();
-	
-	    // Create a new action that doesn't have the promise field and has
-	    // the `seqId` field that represents the sequence id
-	    action = Object.assign(toObject(entries(action).filter(pair => pair[0] !== PROMISE)), { seqId });
-	
-	    dispatch(Object.assign({}, action, { status: "start" }));
-	
-	    // Return the promise so action creators can still compose if they
-	    // want to.
-	    var deferred = defer();
-	    promiseInst.then(value => {
-	      executeSoon(() => {
-	        dispatch(Object.assign({}, action, {
-	          status: "done",
-	          value: value
-	        }));
-	        deferred.resolve(value);
-	      });
-	    }, error => {
-	      executeSoon(() => {
-	        dispatch(Object.assign({}, action, {
-	          status: "error",
-	          error: error.message || error
-	        }));
-	        deferred.reject(error);
-	      });
-	    });
-	    return deferred.promise;
-	  };
-	}
-	
-	exports.promise = promiseMiddleware;
-
-/***/ },
 /* 185 */
-/***/ function(module, exports) {
-
-	
-	let i = 1;
-	function uuid() {
-	  return 'not-really-uuid' + (i++);
-	}
-	
-	module.exports = { uuid };
-
-
-/***/ },
-/* 186 */
-/***/ function(module, exports) {
-
+/***/ function(module, exports, __webpack_require__) {
+
+	var assert = __webpack_require__(186);
+	
 	function reportException(who, exception) {
 	  var msg = who + " threw an exception: ";
 	  console.error(msg, exception);
 	}
 	
-	function assert(condition, message) {
-	  if (!condition) {
-	    var err = new Error("Assertion failure: " + message);
-	    reportException("DevToolsUtils.assert", err);
-	    throw err;
-	  }
-	}
-	
 	function executeSoon(fn) {
 	  setTimeout(fn, 0);
 	}
 	
 	module.exports = {
 	  reportException,
 	  executeSoon,
 	  assert
 	};
 
 /***/ },
+/* 186 */
+/***/ function(module, exports) {
+
+	function assert(condition, message) {
+	  if (!condition) {
+	    throw new Error("Assertion failure: " + message);
+	  }
+	}
+	
+	module.exports = assert;
+
+/***/ },
 /* 187 */
 /***/ function(module, exports) {
 
 	
 	/**
 	 * A middleware that allows thunks (functions) to be dispatched. If
 	 * it's a thunk, it is called with an argument that contains
 	 * `dispatch`, `getState`, and any additional args passed in via the
@@ -21266,22 +21294,21 @@ var Debugger =
 	exports.ADD_BREAKPOINT = "ADD_BREAKPOINT";
 	exports.REMOVE_BREAKPOINT = "REMOVE_BREAKPOINT";
 	exports.ENABLE_BREAKPOINT = "ENABLE_BREAKPOINT";
 	exports.DISABLE_BREAKPOINT = "DISABLE_BREAKPOINT";
 	exports.SET_BREAKPOINT_CONDITION = "SET_BREAKPOINT_CONDITION";
 	exports.TOGGLE_BREAKPOINTS = "TOGGLE_BREAKPOINTS";
 	
 	exports.ADD_SOURCE = "ADD_SOURCE";
-	exports.LOAD_SOURCE_MAP = "LOAD_SOURCE_MAP";
-	exports.CLOSE_TAB = "CLOSE_TAB";
 	exports.ADD_SOURCES = "ADD_SOURCES";
 	exports.LOAD_SOURCE_TEXT = "LOAD_SOURCE_TEXT";
 	exports.SELECT_SOURCE = "SELECT_SOURCE";
 	exports.SELECT_SOURCE_URL = "SELECT_SOURCE_URL";
+	exports.CLOSE_TAB = "CLOSE_TAB";
 	exports.NAVIGATE = "NAVIGATE";
 	exports.RELOAD = "RELOAD";
 	
 	exports.ADD_TABS = "ADD_TABS";
 	exports.SELECT_TAB = "SELECT_TAB";
 	
 	exports.BREAK_ON_NEXT = "BREAK_ON_NEXT";
 	exports.RESUME = "RESUME";
@@ -21294,52 +21321,44 @@ var Debugger =
 	exports.EVALUATE_EXPRESSION = "EVALUATE_EXPRESSION";
 	exports.UPDATE_EXPRESSION = "UPDATE_EXPRESSION";
 	exports.DELETE_EXPRESSION = "DELETE_EXPRESSION";
 
 /***/ },
 /* 191 */
 /***/ function(module, exports, __webpack_require__) {
 
-	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); } }
 	
 	/* 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 fromJS = __webpack_require__(192);
 	var I = __webpack_require__(193);
 	var makeRecord = __webpack_require__(194);
 	
 	var State = makeRecord({
 	  sources: I.Map(),
 	  selectedLocation: undefined,
 	  pendingSelectedLocation: undefined,
 	  sourcesText: I.Map(),
-	  sourceMaps: I.Map(),
 	  tabs: I.List([])
 	});
 	
 	function update() {
 	  var state = arguments.length <= 0 || arguments[0] === undefined ? State() : arguments[0];
 	  var action = arguments[1];
 	
 	  switch (action.type) {
 	    case "ADD_SOURCE":
 	      {
 	        var _source = action.source;
 	        return state.mergeIn(["sources", action.source.id], _source);
 	      }
 	
-	    case "LOAD_SOURCE_MAP":
-	      if (action.status == "done") {
-	        return state.mergeIn(["sourceMaps", action.source.id], action.value.sourceMap);
-	      }
-	      break;
-	
 	    case "SELECT_SOURCE":
 	      return state.set("selectedLocation", {
 	        sourceId: action.source.id,
 	        line: action.line
 	      }).set("pendingSelectedLocation", null).merge({
 	        tabs: updateTabList(state, fromJS(action.source), action.tabIndex)
 	      });
 	
@@ -21350,81 +21369,67 @@ var Debugger =
 	      });
 	
 	    case "CLOSE_TAB":
 	      return state.merge({ tabs: removeSourceFromTabList(state, action.id) }).set("selectedLocation", {
 	        sourceId: getNewSelectedSourceId(state, action.id)
 	      });
 	
 	    case "LOAD_SOURCE_TEXT":
-	      {
-	        var values = void 0;
-	        if (action.status === "done") {
-	          var _action$value = action.value;
-	          var generatedSourceText = _action$value.generatedSourceText;
-	          var originalSourceTexts = _action$value.originalSourceTexts;
-	
-	          values = [generatedSourceText].concat(_toConsumableArray(originalSourceTexts));
-	        } else {
-	          var _source2 = action.source;
-	
-	          values = [_source2];
-	        }
-	
-	        return _updateText(state, action, values);
-	      }
+	      return _updateText(state, action);
 	
 	    case "BLACKBOX":
 	      if (action.status === "done") {
 	        return state.setIn(["sources", action.source.id, "isBlackBoxed"], action.value.isBlackBoxed);
 	      }
 	      break;
 	
 	    case "TOGGLE_PRETTY_PRINT":
 	      if (action.status === "done") {
-	        return _updateText(state, action, [action.value.sourceText]).setIn(["sources", action.source.id, "isPrettyPrinted"], action.value.isPrettyPrinted);
-	      }
-	
-	      return _updateText(state, action, [action.originalSource]);
+	        return _updateText(state, action).setIn(["sources", action.source.id, "isPrettyPrinted"], action.value.isPrettyPrinted);
+	      }
+	
+	      return _updateText(state, action);
 	
 	    case "NAVIGATE":
 	      var source = getSelectedSource({ sources: state });
 	      var _url = source && source.get("url");
 	      return State().set("pendingSelectedLocation", { url: _url });
 	  }
 	
 	  return state;
 	}
 	
-	function _updateText(state, action, values) {
+	// TODO: Action is coerced to `any` unfortunately because how we type
+	// asynchronous actions is wrong. The `value` may be null for the
+	// "start" and "error" states but we don't type it like that. We need
+	// to rethink how we type async actions.
+	function _updateText(state, action) {
+	  var source = action.source;
+	  var sourceText = action.value;
+	
 	  if (action.status === "start") {
 	    // Merge this in, don't set it. That way the previous value is
 	    // still stored here, and we can retrieve it if whatever we're
 	    // doing fails.
-	    return values.reduce((_state, source) => {
-	      return _state.mergeIn(["sourcesText", source.id], {
-	        loading: true
-	      });
-	    }, state);
+	    return state.mergeIn(["sourcesText", source.id], {
+	      loading: true
+	    });
 	  }
 	
 	  if (action.status === "error") {
-	    return values.reduce((_state, source) => {
-	      return _state.setIn(["sourcesText", source.id], I.Map({
-	        error: action.error
-	      }));
-	    }, state);
-	  }
-	
-	  return values.reduce((_state, sourceText) => {
-	    return _state.setIn(["sourcesText", sourceText.id], I.Map({
-	      text: sourceText.text,
-	      contentType: sourceText.contentType
+	    return state.setIn(["sourcesText", source.id], I.Map({
+	      error: action.error
 	    }));
-	  }, state);
+	  }
+	
+	  return state.setIn(["sourcesText", source.id], I.Map({
+	    text: sourceText.text,
+	    contentType: sourceText.contentType
+	  }));
 	}
 	
 	function removeSourceFromTabList(state, id) {
 	  return state.tabs.filter(tab => tab.get("id") != id);
 	}
 	
 	/*
 	 * Adds the new source to the tab list if it is not already there
@@ -21517,20 +21522,16 @@ var Debugger =
 	function getSelectedLocation(state) {
 	  return state.sources.selectedLocation;
 	}
 	
 	function getPendingSelectedLocation(state) {
 	  return state.sources.pendingSelectedLocation;
 	}
 	
-	function getSourceMap(state, sourceId) {
-	  return state.sources.sourceMaps.get(sourceId);
-	}
-	
 	function getPrettySource(state, id) {
 	  var source = getSource(state, id);
 	  if (!source) {
 	    return;
 	  }
 	
 	  return getSourceByURL(state, source.get("url") + ":formatted");
 	}
@@ -21542,17 +21543,16 @@ var Debugger =
 	  getSourceByURL,
 	  getSourceById,
 	  getSources,
 	  getSourceText,
 	  getSourceTabs,
 	  getSelectedSource,
 	  getSelectedLocation,
 	  getPendingSelectedLocation,
-	  getSourceMap,
 	  getPrettySource
 	};
 
 /***/ },
 /* 192 */
 /***/ function(module, exports, __webpack_require__) {
 
 	
@@ -26612,17 +26612,17 @@ var Debugger =
 
 	
 	/* 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 fromJS = __webpack_require__(192);
 	
-	var _require = __webpack_require__(176);
+	var _require = __webpack_require__(183);
 	
 	var updateObj = _require.updateObj;
 	
 	var I = __webpack_require__(193);
 	var makeRecord = __webpack_require__(194);
 	
 	var State = makeRecord({
 	  breakpoints: I.Map(),
@@ -27054,65 +27054,44 @@ var Debugger =
 	};
 
 /***/ },
 /* 199 */
 /***/ function(module, exports, __webpack_require__) {
 
 	
 	
-	var URL = __webpack_require__(200);
-	var path = __webpack_require__(205);
 	var sources = __webpack_require__(191);
 	var pause = __webpack_require__(198);
 	var breakpoints = __webpack_require__(195);
 	
 	function getTabs(state) {
 	  return state.tabs.get("tabs");
 	}
 	
 	function getSelectedTab(state) {
 	  return state.tabs.get("selectedTab");
 	}
 	
-	function getSourceMapURL(state, source) {
-	  if (path.isURL(source.sourceMapURL)) {
-	    // If it's a full URL already, just use it.
-	    return source.sourceMapURL;
-	  } else if (path.isAbsolute(source.sourceMapURL)) {
-	    // If it's an absolute path, it should be resolved relative to the
-	
-	    var urlObj = URL.parse(source.url);
-	    var base = urlObj.protocol + "//" + urlObj.host;
-	    return base + source.sourceMapURL;
-	  }
-	  // Otherwise, it's a relative path and should be resolved relative
-	  // to the source.
-	  return path.dirname(source.url) + "/" + source.sourceMapURL;
-	}
-	
 	/**
 	 * @param object - location
 	 */
 	
 	module.exports = {
 	  getSource: sources.getSource,
 	  getSourceByURL: sources.getSourceByURL,
 	  getSourceById: sources.getSourceById,
 	  getSources: sources.getSources,
 	  getSourceText: sources.getSourceText,
 	  getSourceTabs: sources.getSourceTabs,
 	  getSelectedSource: sources.getSelectedSource,
 	  getSelectedLocation: sources.getSelectedLocation,
 	  getPendingSelectedLocation: sources.getPendingSelectedLocation,
-	  getSourceMap: sources.getSourceMap,
 	  getPrettySource: sources.getPrettySource,
 	
-	  getSourceMapURL,
-	
 	  getBreakpoint: breakpoints.getBreakpoint,
 	  getBreakpoints: breakpoints.getBreakpoints,
 	  getBreakpointsForSource: breakpoints.getBreakpointsForSource,
 	  getBreakpointsDisabled: breakpoints.getBreakpointsDisabled,
 	  getBreakpointsLoading: breakpoints.getBreakpointsLoading,
 	
 	  getTabs,
 	  getSelectedTab,
@@ -27126,16 +27105,1459 @@ var Debugger =
 	  getFrames: pause.getFrames,
 	  getSelectedFrame: pause.getSelectedFrame
 	};
 
 /***/ },
 /* 200 */
 /***/ function(module, exports, __webpack_require__) {
 
+	var React = __webpack_require__(17);
+	
+	var _require = __webpack_require__(15);
+	
+	var connect = _require.connect;
+	
+	var classnames = __webpack_require__(201);
+	
+	var _require2 = __webpack_require__(199);
+	
+	var getTabs = _require2.getTabs;
+	
+	
+	__webpack_require__(202);
+	var dom = React.DOM;
+	
+	var githubUrl = "https://github.com/devtools-html/debugger.html/blob/master";
+	
+	function getTabsByBrowser(tabs, browser) {
+	  return tabs.valueSeq().filter(tab => tab.get("browser") == browser);
+	}
+	
+	function renderTabs(tabTitle, tabs, paramName) {
+	  if (tabs.count() == 0) {
+	    return null;
+	  }
+	
+	  return dom.div({ className: `tab-group ${ tabTitle }` }, dom.div({ className: "tab-group-title" }, tabTitle), dom.ul({ className: "tab-list" }, tabs.valueSeq().map(tab => dom.li({ "className": "tab",
+	    "key": tab.get("id"),
+	    "onClick": () => {
+	      window.location = "/?" + paramName + "=" + tab.get("id");
+	    } }, dom.div({ className: "tab-title" }, tab.get("title")), dom.div({ className: "tab-url" }, tab.get("url"))))));
+	}
+	
+	function renderMessage(noTabs) {
+	  return dom.div({ className: classnames("connect-message", { "not-connected": noTabs }) }, dom.p(null, noTabs && "No remote tabs found. ", "You may be looking to ", dom.a({
+	    href: `/?ws=${ document.location.hostname }:9229/node`
+	  }, "connect to Node"), "."), dom.p(null, "Make sure you run ", dom.a({ href: `${ githubUrl }/CONTRIBUTING.md#firefox` }, "Firefox"), ", ", dom.a({ href: `${ githubUrl }/CONTRIBUTING.md#chrome` }, "Chrome"), " or ", dom.a({ href: `${ githubUrl }/CONTRIBUTING.md#nodejs` }, "Node"), " with the right flags."));
+	}
+	function Tabs(_ref) {
+	  var tabs = _ref.tabs;
+	
+	  var firefoxTabs = getTabsByBrowser(tabs, "firefox");
+	  var chromeTabs = getTabsByBrowser(tabs, "chrome");
+	
+	  return dom.div({ className: "tabs theme-light" }, renderTabs("Firefox Tabs", firefoxTabs, "firefox-tab"), renderTabs("Chrome Tabs", chromeTabs, "chrome-tab"), renderMessage(tabs.isEmpty()));
+	}
+	
+	module.exports = connect(state => ({ tabs: getTabs(state) }))(Tabs);
+
+/***/ },
+/* 201 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
+	  Copyright (c) 2016 Jed Watson.
+	  Licensed under the MIT License (MIT), see
+	  http://jedwatson.github.io/classnames
+	*/
+	/* global define */
+	
+	(function () {
+		'use strict';
+	
+		var hasOwn = {}.hasOwnProperty;
+	
+		function classNames () {
+			var classes = [];
+	
+			for (var i = 0; i < arguments.length; i++) {
+				var arg = arguments[i];
+				if (!arg) continue;
+	
+				var argType = typeof arg;
+	
+				if (argType === 'string' || argType === 'number') {
+					classes.push(arg);
+				} else if (Array.isArray(arg)) {
+					classes.push(classNames.apply(null, arg));
+				} else if (argType === 'object') {
+					for (var key in arg) {
+						if (hasOwn.call(arg, key) && arg[key]) {
+							classes.push(key);
+						}
+					}
+				}
+			}
+	
+			return classes.join(' ');
+		}
+	
+		if (typeof module !== 'undefined' && module.exports) {
+			module.exports = classNames;
+		} else if (true) {
+			// register as 'classnames', consistent with npm package name
+			!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = function () {
+				return classNames;
+			}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+		} else {
+			window.classNames = classNames;
+		}
+	}());
+
+
+/***/ },
+/* 202 */
+/***/ function(module, exports) {
+
+	// removed by extract-text-webpack-plugin
+
+/***/ },
+/* 203 */,
+/* 204 */,
+/* 205 */,
+/* 206 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var React = __webpack_require__(17);
+	var dom = React.DOM;
+	var PropTypes = React.PropTypes;
+	var createFactory = React.createFactory;
+	
+	var _require = __webpack_require__(15);
+	
+	var connect = _require.connect;
+	
+	var _require2 = __webpack_require__(2);
+	
+	var bindActionCreators = _require2.bindActionCreators;
+	
+	var _require3 = __webpack_require__(207);
+	
+	var cmdString = _require3.cmdString;
+	
+	var classnames = __webpack_require__(201);
+	var actions = __webpack_require__(209);
+	
+	var _require4 = __webpack_require__(46);
+	
+	var isFirefoxPanel = _require4.isFirefoxPanel;
+	
+	var _require5 = __webpack_require__(199);
+	
+	var getSources = _require5.getSources;
+	var getSelectedSource = _require5.getSelectedSource;
+	
+	var _require6 = __webpack_require__(183);
+	
+	var endTruncateStr = _require6.endTruncateStr;
+	
+	var _require7 = __webpack_require__(212);
+	
+	var parseURL = _require7.parse;
+	
+	var _require8 = __webpack_require__(241);
+	
+	var KeyShortcuts = _require8.KeyShortcuts;
+	
+	
+	__webpack_require__(242);
+	__webpack_require__(244);
+	
+	// Using this static variable allows webpack to know at compile-time
+	// to avoid this require and not include it at all in the output.
+	if (false) {
+	  require("../lib/themes/light-theme.css");
+	}
+	
+	var Sources = createFactory(__webpack_require__(246));
+	var Editor = createFactory(__webpack_require__(354));
+	var SplitBox = createFactory(__webpack_require__(363));
+	var RightSidebar = createFactory(__webpack_require__(365));
+	var SourceTabs = createFactory(__webpack_require__(424));
+	var Svg = __webpack_require__(328);
+	var Autocomplete = createFactory(__webpack_require__(429));
+	
+	function searchResults(sources) {
+	  function getSourcePath(source) {
+	    var _parseURL = parseURL(source.get("url"));
+	
+	    var path = _parseURL.path;
+	
+	    return endTruncateStr(path, 50);
+	  }
+	
+	  return sources.valueSeq().filter(source => source.get("url")).map(source => ({
+	    value: getSourcePath(source),
+	    title: getSourcePath(source).split("/").pop(),
+	    subtitle: getSourcePath(source),
+	    id: source.get("id")
+	  })).toJS();
+	}
+	
+	var App = React.createClass({
+	  propTypes: {
+	    sources: PropTypes.object,
+	    selectSource: PropTypes.func,
+	    selectedSource: PropTypes.object
+	  },
+	
+	  displayName: "App",
+	
+	  getInitialState() {
+	    return {
+	      searchOn: false
+	    };
+	  },
+	
+	  getChildContext() {
+	    return {
+	      shortcuts: this.shortcuts
+	    };
+	  },
+	
+	  componentDidMount() {
+	    this.shortcuts = new KeyShortcuts({ window });
+	
+	    this.shortcuts.on("CmdOrCtrl+P", this.toggleSourcesSearch);
+	    window.addEventListener("keydown", this.onKeyDown);
+	  },
+	
+	  componentWillUnmount() {
+	    this.shortcuts.off("CmdOrCtrl+P", this.toggleSourcesSearch);
+	    window.removeEventListener("keydown", this.onKeyDown);
+	  },
+	
+	  toggleSourcesSearch(key, e) {
+	    e.preventDefault();
+	    this.setState({ searchOn: !this.state.searchOn });
+	  },
+	
+	  onKeyDown(e) {
+	    if (this.state.searchOn && e.key === "Escape") {
+	      this.setState({ searchOn: false });
+	      e.preventDefault();
+	    }
+	  },
+	
+	  closeSourcesSearch() {
+	    this.setState({ searchOn: false });
+	  },
+	
+	  renderSourcesSearch() {
+	    return dom.div({ className: "search-container" }, Autocomplete({
+	      selectItem: result => {
+	        this.props.selectSource(result.id);
+	        this.setState({ searchOn: false });
+	      },
+	      items: searchResults(this.props.sources)
+	    }), dom.div({ className: "close-button" }, Svg("close", { onClick: this.closeSourcesSearch })));
+	  },
+	
+	  renderWelcomeBox() {
+	    return dom.div({ className: "welcomebox" }, `${ cmdString() }+P to search for files`);
+	  },
+	
+	  renderCenterPane() {
+	    return dom.div({ className: "center-pane" }, dom.div({ className: "editor-container" }, SourceTabs(), Editor(), !this.props.selectedSource ? this.renderWelcomeBox() : null, this.state.searchOn ? this.renderSourcesSearch() : null));
+	  },
+	
+	  render: function () {
+	    return dom.div({ className: classnames("debugger theme-body", { "theme-light": !isFirefoxPanel() }) }, SplitBox({
+	      style: { width: "100vh" },
+	      initialSize: "300px",
+	      minSize: 10,
+	      maxSize: "50%",
+	      splitterSize: 1,
+	      startPanel: Sources({ sources: this.props.sources }),
+	      endPanel: SplitBox({
+	        initialSize: "300px",
+	        minSize: 10,
+	        maxSize: "80%",
+	        splitterSize: 1,
+	        endPanelControl: true,
+	        startPanel: this.renderCenterPane(this.props),
+	        endPanel: RightSidebar()
+	      })
+	    }));
+	  }
+	});
+	
+	App.childContextTypes = {
+	  shortcuts: PropTypes.object
+	};
+	
+	module.exports = connect(state => ({ sources: getSources(state),
+	  selectedSource: getSelectedSource(state) }), dispatch => bindActionCreators(actions, dispatch))(App);
+
+/***/ },
+/* 207 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var _require = __webpack_require__(208);
+	
+	var Services = _require.Services;
+	
+	
+	function cmdString() {
+	  return Services.appinfo.OS === "Darwin" ? "⌘" : "Ctrl";
+	}
+	
+	module.exports = {
+	  cmdString
+	};
+
+/***/ },
+/* 208 */
+/***/ function(module, exports) {
+
+	/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+	/* vim: set ts=2 et sw=2 tw=80: */
+	/* This Source Code Form is subject to the terms of the Mozilla Public
+	 * License, v. 2.0. If a copy of the MPL was not distributed with this
+	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+	
+	"use strict";
+	
+	/* globals localStorage, window, document, NodeFilter */
+	
+	// Some constants from nsIPrefBranch.idl.
+	const PREF_INVALID = 0;
+	const PREF_STRING = 32;
+	const PREF_INT = 64;
+	const PREF_BOOL = 128;
+	const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed";
+	
+	/**
+	 * Create a new preference object.
+	 *
+	 * @param {PrefBranch} branch the branch holding this preference
+	 * @param {String} name the base name of this preference
+	 * @param {String} fullName the fully-qualified name of this preference
+	 */
+	function Preference(branch, name, fullName) {
+	  this.branch = branch;
+	  this.name = name;
+	  this.fullName = fullName;
+	  this.defaultValue = null;
+	  this.hasUserValue = false;
+	  this.userValue = null;
+	  this.type = null;
+	}
+	
+	Preference.prototype = {
+	  /**
+	   * Return this preference's current value.
+	   *
+	   * @return {Any} The current value of this preference.  This may
+	   *         return a string, a number, or a boolean depending on the
+	   *         preference's type.
+	   */
+	  get: function () {
+	    if (this.hasUserValue) {
+	      return this.userValue;
+	    }
+	    return this.defaultValue;
+	  },
+	
+	  /**
+	   * Set the preference's value.  The new value is assumed to be a
+	   * user value.  After setting the value, this function emits a
+	   * change notification.
+	   *
+	   * @param {Any} value the new value
+	   */
+	  set: function (value) {
+	    if (!this.hasUserValue || value !== this.userValue) {
+	      this.userValue = value;
+	      this.hasUserValue = true;
+	      this.saveAndNotify();
+	    }
+	  },
+	
+	  /**
+	   * Set the default value for this preference, and emit a
+	   * notification if this results in a visible change.
+	   *
+	   * @param {Any} value the new default value
+	   */
+	  setDefault: function (value) {
+	    if (this.defaultValue !== value) {
+	      this.defaultValue = value;
+	      if (!this.hasUserValue) {
+	        this.saveAndNotify();
+	      }
+	    }
+	  },
+	
+	  /**
+	   * If this preference has a user value, clear it.  If a change was
+	   * made, emit a change notification.
+	   */
+	  clearUserValue: function () {
+	    if (this.hasUserValue) {
+	      this.userValue = null;
+	      this.hasUserValue = false;
+	      this.saveAndNotify();
+	    }
+	  },
+	
+	  /**
+	   * Helper function to write the preference's value to local storage
+	   * and then emit a change notification.
+	   */
+	  saveAndNotify: function () {
+	    let store = {
+	      type: this.type,
+	      defaultValue: this.defaultValue,
+	      hasUserValue: this.hasUserValue,
+	      userValue: this.userValue,
+	    };
+	
+	    localStorage.setItem(this.fullName, JSON.stringify(store));
+	    this.branch._notify(this.name);
+	  },
+	
+	  /**
+	   * Change this preference's value without writing it back to local
+	   * storage.  This is used to handle changes to local storage that
+	   * were made externally.
+	   *
+	   * @param {Number} type one of the PREF_* values
+	   * @param {Any} userValue the user value to use if the pref does not exist
+	   * @param {Any} defaultValue the default value to use if the pref
+	   *        does not exist
+	   * @param {Boolean} hasUserValue if a new pref is created, whether
+	   *        the default value is also a user value
+	   * @param {Object} store the new value of the preference.  It should
+	   *        be of the form {type, defaultValue, hasUserValue, userValue};
+	   *        where |type| is one of the PREF_* type constants; |defaultValue|
+	   *        and |userValue| are the default and user values, respectively;
+	   *        and |hasUserValue| is a boolean indicating whether the user value
+	   *        is valid
+	   */
+	  storageUpdated: function (type, userValue, hasUserValue, defaultValue) {
+	    this.type = type;
+	    this.defaultValue = defaultValue;
+	    this.hasUserValue = hasUserValue;
+	    this.userValue = userValue;
+	    // There's no need to write this back to local storage, since it
+	    // came from there; and this avoids infinite event loops.
+	    this.branch._notify(this.name);
+	  },
+	};
+	
+	/**
+	 * Create a new preference branch.  This object conforms largely to
+	 * nsIPrefBranch and nsIPrefService, though it only implements the
+	 * subset needed by devtools.
+	 *
+	 * @param {PrefBranch} parent the parent branch, or null for the root
+	 *        branch.
+	 * @param {String} name the base name of this branch
+	 * @param {String} fullName the fully-qualified name of this branch
+	 */
+	function PrefBranch(parent, name, fullName) {
+	  this._parent = parent;
+	  this._name = name;
+	  this._fullName = fullName;
+	  this._observers = {};
+	  this._children = {};
+	
+	  if (!parent) {
+	    this._initializeRoot();
+	  }
+	}
+	
+	PrefBranch.prototype = {
+	  PREF_INVALID: PREF_INVALID,
+	  PREF_STRING: PREF_STRING,
+	  PREF_INT: PREF_INT,
+	  PREF_BOOL: PREF_BOOL,
+	
+	  /** @see nsIPrefBranch.root.  */
+	  get root() {
+	    return this._fullName;
+	  },
+	
+	  /** @see nsIPrefBranch.getPrefType.  */
+	  getPrefType: function (prefName) {
+	    return this._findPref(prefName).type;
+	  },
+	
+	  /** @see nsIPrefBranch.getBoolPref.  */
+	  getBoolPref: function (prefName) {
+	    let thePref = this._findPref(prefName);
+	    if (thePref.type !== PREF_BOOL) {
+	      throw new Error(`${prefName} does not have bool type`);
+	    }
+	    return thePref.get();
+	  },
+	
+	  /** @see nsIPrefBranch.setBoolPref.  */
+	  setBoolPref: function (prefName, value) {
+	    if (typeof value !== "boolean") {
+	      throw new Error("non-bool passed to setBoolPref");
+	    }
+	    let thePref = this._findOrCreatePref(prefName, value, true, value);
+	    if (thePref.type !== PREF_BOOL) {
+	      throw new Error(`${prefName} does not have bool type`);
+	    }
+	    thePref.set(value);
+	  },
+	
+	  /** @see nsIPrefBranch.getCharPref.  */
+	  getCharPref: function (prefName) {
+	    let thePref = this._findPref(prefName);
+	    if (thePref.type !== PREF_STRING) {
+	      throw new Error(`${prefName} does not have string type`);
+	    }
+	    return thePref.get();
+	  },
+	
+	  /** @see nsIPrefBranch.setCharPref.  */
+	  setCharPref: function (prefName, value) {
+	    if (typeof value !== "string") {
+	      throw new Error("non-string passed to setCharPref");
+	    }
+	    let thePref = this._findOrCreatePref(prefName, value, true, value);
+	    if (thePref.type !== PREF_STRING) {
+	      throw new Error(`${prefName} does not have string type`);
+	    }
+	    thePref.set(value);
+	  },
+	
+	  /** @see nsIPrefBranch.getIntPref.  */
+	  getIntPref: function (prefName) {
+	    let thePref = this._findPref(prefName);
+	    if (thePref.type !== PREF_INT) {
+	      throw new Error(`${prefName} does not have int type`);
+	    }
+	    return thePref.get();
+	  },
+	
+	  /** @see nsIPrefBranch.setIntPref.  */
+	  setIntPref: function (prefName, value) {
+	    if (typeof value !== "number") {
+	      throw new Error("non-number passed to setIntPref");
+	    }
+	    let thePref = this._findOrCreatePref(prefName, value, true, value);
+	    if (thePref.type !== PREF_INT) {
+	      throw new Error(`${prefName} does not have int type`);
+	    }
+	    thePref.set(value);
+	  },
+	
+	  /** @see nsIPrefBranch.clearUserPref */
+	  clearUserPref: function (prefName) {
+	    let thePref = this._findPref(prefName);
+	    thePref.clearUserValue();
+	  },
+	
+	  /** @see nsIPrefBranch.prefHasUserValue */
+	  prefHasUserValue: function (prefName) {
+	    let thePref = this._findPref(prefName);
+	    return thePref.hasUserValue;
+	  },
+	
+	  /** @see nsIPrefBranch.addObserver */
+	  addObserver: function (domain, observer, holdWeak) {
+	    if (domain !== "" && !domain.endsWith(".")) {
+	      throw new Error("invalid domain to addObserver: " + domain);
+	    }
+	    if (holdWeak) {
+	      throw new Error("shim prefs only supports strong observers");
+	    }
+	
+	    if (!(domain in this._observers)) {
+	      this._observers[domain] = [];
+	    }
+	    this._observers[domain].push(observer);
+	  },
+	
+	  /** @see nsIPrefBranch.removeObserver */
+	  removeObserver: function (domain, observer) {
+	    if (!(domain in this._observers)) {
+	      return;
+	    }
+	    let index = this._observers[domain].indexOf(observer);
+	    if (index >= 0) {
+	      this._observers[domain].splice(index, 1);
+	    }
+	  },
+	
+	  /** @see nsIPrefService.savePrefFile */
+	  savePrefFile: function (file) {
+	    if (file) {
+	      throw new Error("shim prefs only supports null file in savePrefFile");
+	    }
+	    // Nothing to do - this implementation always writes back.
+	  },
+	
+	  /** @see nsIPrefService.getBranch */
+	  getBranch: function (prefRoot) {
+	    if (!prefRoot) {
+	      return this;
+	    }
+	    if (prefRoot.endsWith(".")) {
+	      prefRoot = prefRoot.slice(0, -1);
+	    }
+	    // This is a bit weird since it could erroneously return a pref,
+	    // not a pref branch.
+	    return this._findPref(prefRoot);
+	  },
+	
+	  /**
+	   * Helper function to find either a Preference or PrefBranch object
+	   * given its name.  If the name is not found, throws an exception.
+	   *
+	   * @param {String} prefName the fully-qualified preference name
+	   * @return {Object} Either a Preference or PrefBranch object
+	   */
+	  _findPref: function (prefName) {
+	    let branchNames = prefName.split(".");
+	    let branch = this;
+	
+	    for (let branchName of branchNames) {
+	      branch = branch._children[branchName];
+	      if (!branch) {
+	        throw new Error("could not find pref branch " + prefName);
+	      }
+	    }
+	
+	    return branch;
+	  },
+	
+	  /**
+	   * Helper function to notify any observers when a preference has
+	   * changed.  This will also notify the parent branch for further
+	   * reporting.
+	   *
+	   * @param {String} relativeName the name of the updated pref,
+	   *        relative to this branch
+	   */
+	  _notify: function (relativeName) {
+	    for (let domain in this._observers) {
+	      if (relativeName.startsWith(domain)) {
+	        // Allow mutation while walking.
+	        let localList = this._observers[domain].slice();
+	        for (let observer of localList) {
+	          try {
+	            observer.observe(this, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID,
+	                             relativeName);
+	          } catch (e) {
+	            console.error(e);
+	          }
+	        }
+	      }
+	    }
+	
+	    if (this._parent) {
+	      this._parent._notify(this._name + "." + relativeName);
+	    }
+	  },
+	
+	  /**
+	   * Helper function to create a branch given an array of branch names
+	   * representing the path of the new branch.
+	   *
+	   * @param {Array} branchList an array of strings, one per component
+	   *        of the branch to be created
+	   * @return {PrefBranch} the new branch
+	   */
+	  _createBranch: function (branchList) {
+	    let parent = this;
+	    for (let branch of branchList) {
+	      if (!parent._children[branch]) {
+	        parent._children[branch] = new PrefBranch(parent, branch,
+	                                                  parent.root + "." + branch);
+	      }
+	      parent = parent._children[branch];
+	    }
+	    return parent;
+	  },
+	
+	  /**
+	   * Create a new preference.  The new preference is assumed to be in
+	   * local storage already, and the new value is taken from there.
+	   *
+	   * @param {String} keyName the full-qualified name of the preference.
+	   *        This is also the name of the key in local storage.
+	   * @param {Any} userValue the user value to use if the pref does not exist
+	   * @param {Any} defaultValue the default value to use if the pref
+	   *        does not exist
+	   * @param {Boolean} hasUserValue if a new pref is created, whether
+	   *        the default value is also a user value
+	   */
+	  _findOrCreatePref: function (keyName, userValue, hasUserValue, defaultValue) {
+	    let branchName = keyName.split(".");
+	    let prefName = branchName.pop();
+	
+	    let branch = this._createBranch(branchName);
+	    if (!(prefName in branch._children)) {
+	      if (hasUserValue && typeof (userValue) !== typeof (defaultValue)) {
+	        throw new Error("inconsistent values when creating " + keyName);
+	      }
+	
+	      let type;
+	      switch (typeof (defaultValue)) {
+	        case "boolean":
+	          type = PREF_BOOL;
+	          break;
+	        case "number":
+	          type = PREF_INT;
+	          break;
+	        case "string":
+	          type = PREF_STRING;
+	          break;
+	        default:
+	          throw new Error("unhandled argument type: " + typeof (defaultValue));
+	      }
+	
+	      let thePref = new Preference(branch, prefName, keyName);
+	      thePref.storageUpdated(type, userValue, hasUserValue, defaultValue);
+	      branch._children[prefName] = thePref;
+	    }
+	
+	    return branch._children[prefName];
+	  },
+	
+	  /**
+	   * Helper function that is called when local storage changes.  This
+	   * updates the preferences and notifies pref observers as needed.
+	   *
+	   * @param {StorageEvent} event the event representing the local
+	   *        storage change
+	   */
+	  _onStorageChange: function (event) {
+	    if (event.storageArea !== localStorage) {
+	      return;
+	    }
+	
+	    // Ignore delete events.  Not clear what's correct.
+	    if (event.key === null || event.newValue === null) {
+	      return;
+	    }
+	
+	    let {type, userValue, hasUserValue, defaultValue} =
+	        JSON.parse(event.newValue);
+	    if (event.oldValue === null) {
+	      this._findOrCreatePref(event.key, userValue, hasUserValue, defaultValue);
+	    } else {
+	      let thePref = this._findPref(event.key);
+	      thePref.storageUpdated(type, userValue, hasUserValue, defaultValue);
+	    }
+	  },
+	
+	  /**
+	   * Helper function to initialize the root PrefBranch.
+	   */
+	  _initializeRoot: function () {
+	    try {
+	      if (localStorage.length === 0) {
+	        // FIXME - this is where we'll load devtools.js to install the
+	        // default prefs.
+	      }
+	    } catch(e) {
+	      // Couldn't access localStorage; bail. This happens in the
+	      // Firefox panel because Chrome-privileged code can't access it.
+	      return;
+	    }
+	
+	    // Read the prefs from local storage and create the local
+	    // representations.
+	    for (let i = 0; i < localStorage.length; ++i) {
+	      let keyName = localStorage.key(i);
+	      try {
+	        let {userValue, hasUserValue, defaultValue} =
+	            JSON.parse(localStorage.getItem(keyName));
+	
+	        this._findOrCreatePref(keyName, userValue, hasUserValue, defaultValue);
+	      } catch (e) {
+	      }
+	    }
+	
+	    this._onStorageChange = this._onStorageChange.bind(this);
+	    window.addEventListener("storage", this._onStorageChange);
+	  },
+	};
+	
+	const Services = {
+	  /**
+	   * An implementation of nsIPrefService that is based on local
+	   * storage.  Only the subset of nsIPrefService that is actually used
+	   * by devtools is implemented here.
+	   */
+	  prefs: new PrefBranch(null, "", ""),
+	
+	  /**
+	   * An implementation of Services.appinfo that holds just the
+	   * properties needed by devtools.
+	   */
+	  appinfo: {
+	    get OS() {
+	      const os = window.navigator.userAgent;
+	      if (os) {
+	        if (os.includes("Linux")) {
+	          return "Linux";
+	        } else if (os.includes("Windows")) {
+	          return "WINNT";
+	        } else if (os.includes("Mac")) {
+	          return "Darwin";
+	        }
+	      }
+	      return "Unknown";
+	    },
+	
+	    // It's fine for this to be an approximation.
+	    get name() {
+	      return window.navigator.userAgent;
+	    },
+	
+	    // It's fine for this to be an approximation.
+	    get version() {
+	      return window.navigator.appVersion;
+	    },
+	
+	    // This is only used by telemetry, which is disabled for the
+	    // content case.  So, being totally wrong is ok.
+	    get is64Bit() {
+	      return true;
+	    },
+	  },
+	
+	  /**
+	   * A no-op implementation of Services.telemetry.  This supports just
+	   * the subset of Services.telemetry that is used by devtools.
+	   */
+	  telemetry: {
+	    getHistogramById: function (name) {
+	      return {
+	        add: () => {}
+	      };
+	    },
+	
+	    getKeyedHistogramById: function (name) {
+	      return {
+	        add: () => {}
+	      };
+	    },
+	  },
+	
+	  /**
+	   * An implementation of Services.focus that holds just the
+	   * properties and methods needed by devtools.
+	   * @see nsIFocusManager.idl for details.
+	   */
+	  focus: {
+	    // These values match nsIFocusManager in order to make testing a
+	    // bit simpler.
+	    MOVEFOCUS_FORWARD: 1,
+	    MOVEFOCUS_BACKWARD: 2,
+	
+	    get focusedElement() {
+	      if (!document.hasFocus()) {
+	        return null;
+	      }
+	      return document.activeElement;
+	    },
+	
+	    moveFocus: function (window, startElement, type, flags) {
+	      if (flags !== 0) {
+	        throw new Error("shim Services.focus.moveFocus only accepts flags===0");
+	      }
+	      if (type !== Services.focus.MOVEFOCUS_FORWARD
+	          && type !== Services.focus.MOVEFOCUS_BACKWARD) {
+	        throw new Error("shim Services.focus.moveFocus only supports " +
+	                        " MOVEFOCUS_FORWARD and MOVEFOCUS_BACKWARD");
+	      }
+	
+	      if (!startElement) {
+	        startElement = document.activeElement || document;
+	      }
+	
+	      let iter = document.createTreeWalker(document, NodeFilter.SHOW_ELEMENT, {
+	        acceptNode: function (node) {
+	          let tabIndex = node.getAttribute("tabindex");
+	          if (tabIndex === "-1") {
+	            return NodeFilter.FILTER_SKIP;
+	          }
+	          node.focus();
+	          if (document.activeElement == node) {
+	            return NodeFilter.FILTER_ACCEPT;
+	          }
+	          return NodeFilter.FILTER_SKIP;
+	        }
+	      });
+	
+	      iter.currentNode = startElement;
+	
+	      // Sets the focus via side effect in the filter.
+	      if (type === Services.focus.MOVEFOCUS_FORWARD) {
+	        iter.nextNode();
+	      } else {
+	        iter.previousNode();
+	      }
+	    },
+	  },
+	};
+	
+	/**
+	 * Create a new preference.  This is used during startup (see
+	 * devtools/client/preferences/devtools.js) to install the
+	 * default preferences.
+	 *
+	 * @param {String} name the name of the preference
+	 * @param {Any} value the default value of the preference
+	 */
+	function pref(name, value) {
+	  let thePref = Services.prefs._findOrCreatePref(name, value, true, value);
+	  thePref.setDefault(value);
+	}
+	
+	exports.Services = Services;
+	// This is exported to silence eslint and, at some point, perhaps to
+	// provide it when loading devtools.js in order to install the default
+	// preferences.
+	exports.pref = pref;
+
+
+/***/ },
+/* 209 */
+/***/ function(module, exports, __webpack_require__) {
+
+	
+	
+	var breakpoints = __webpack_require__(210);
+	var eventListeners = __webpack_require__(234);
+	var sources = __webpack_require__(235);
+	var tabs = __webpack_require__(238);
+	var pause = __webpack_require__(239);
+	var navigation = __webpack_require__(240);
+	
+	module.exports = Object.assign(navigation, breakpoints, eventListeners, sources, tabs, pause);
+
+/***/ },
+/* 210 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
+	
+	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) { return step("next", value); }, function (err) { return 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/. */
+	
+	/**
+	 * Redux actions for breakpoints
+	 * @module actions/breakpoints
+	 */
+	
+	var constants = __webpack_require__(190);
+	
+	var _require = __webpack_require__(182);
+	
+	var PROMISE = _require.PROMISE;
+	
+	var _require2 = __webpack_require__(199);
+	
+	var getBreakpoint = _require2.getBreakpoint;
+	var getBreakpoints = _require2.getBreakpoints;
+	
+	var _require3 = __webpack_require__(211);
+	
+	var getOriginalLocation = _require3.getOriginalLocation;
+	var getGeneratedLocation = _require3.getGeneratedLocation;
+	var isOriginalId = _require3.isOriginalId;
+	
+	/**
+	 * Argument parameters via Thunk middleware for {@link https://github.com/gaearon/redux-thunk|Redux Thunk}
+	 *
+	 * @memberof actions/breakpoints
+	 * @static
+	 * @typedef {Object} ThunkArgs
+	 */
+	
+	function _breakpointExists(state, location) {
+	  var currentBp = getBreakpoint(state, location);
+	  return currentBp && !currentBp.disabled;
+	}
+	
+	function _getOrCreateBreakpoint(state, location, condition) {
+	  return getBreakpoint(state, location) || { location, condition };
+	}
+	
+	/**
+	 * Enabling a breakpoint calls {@link addBreakpoint}
+	 * which will reuse the existing breakpoint information that is stored.
+	 *
+	 * @memberof actions/breakpoints
+	 * @static
+	 */
+	function enableBreakpoint(location) {
+	  return addBreakpoint(location);
+	}
+	
+	/**
+	 * Add a new or enable an existing breakpoint
+	 *
+	 * @memberof actions/breakpoints
+	 * @static
+	 * @param {String} $1.condition Conditional breakpoint condition value
+	 * @param {Function} $1.getTextForLine Get the text to represent the line
+	 */
+	function addBreakpoint(location) {
+	  var _ref = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
+	
+	  var condition = _ref.condition;
+	  var getTextForLine = _ref.getTextForLine;
+	
+	  return _ref2 => {
+	    var dispatch = _ref2.dispatch;
+	    var getState = _ref2.getState;
+	    var client = _ref2.client;
+	
+	    if (_breakpointExists(getState(), location)) {
+	      return Promise.resolve();
+	    }
+	
+	    var bp = _getOrCreateBreakpoint(getState(), location, condition);
+	
+	    return dispatch({
+	      type: constants.ADD_BREAKPOINT,
+	      breakpoint: bp,
+	      condition: condition,
+	      [PROMISE]: _asyncToGenerator(function* () {
+	        location = yield getGeneratedLocation(bp.location, getState());
+	
+	        var _ref4 = yield client.setBreakpoint(location, bp.condition, isOriginalId(bp.location.sourceId));
+	
+	        var id = _ref4.id;
+	        var actualLocation = _ref4.actualLocation;
+	
+	
+	        actualLocation = yield getOriginalLocation(actualLocation);
+	
+	        // If this breakpoint is being re-enabled, it already has a
+	        // text snippet.
+	        var text = bp.text;
+	        if (!text) {
+	          text = getTextForLine ? getTextForLine(actualLocation.line) : "";
+	        }
+	
+	        return { id, actualLocation, text };
+	      })()
+	    });
+	  };
+	}
+	
+	/**
+	 * Disable a single breakpoint
+	 *
+	 * @memberof actions/breakpoints
+	 * @static
+	 */
+	function disableBreakpoint(location) {
+	  return _removeOrDisableBreakpoint(location, true);
+	}
+	
+	/**
+	 * Remove a single breakpoint
+	 *
+	 * @memberof actions/breakpoints
+	 * @static
+	 */
+	function removeBreakpoint(location) {
+	  return _removeOrDisableBreakpoint(location);
+	}
+	
+	function _removeOrDisableBreakpoint(location, isDisabled) {
+	  return _ref5 => {
+	    var dispatch = _ref5.dispatch;
+	    var getState = _ref5.getState;
+	    var client = _ref5.client;
+	
+	    var bp = 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");
+	    }
+	
+	    var action = {
+	      type: constants.REMOVE_BREAKPOINT,
+	      breakpoint: bp,
+	      disabled: isDisabled
+	    };
+	
+	    // If the breakpoint is already disabled, we don't need to remove
+	    // it from the server. We just need to dispatch an action
+	    // simulating a successful server request to remove it, and it
+	    // will be removed completely from the state.
+	    if (!bp.disabled) {
+	      return dispatch(Object.assign({}, action, {
+	        [PROMISE]: client.removeBreakpoint(bp.id)
+	      }));
+	    }
+	    return dispatch(Object.assign({}, action, { status: "done" }));
+	  };
+	}
+	
+	/**
+	 * Toggle All Breakpoints
+	 *
+	 * @memberof actions/breakpoints
+	 * @static
+	 */
+	function toggleAllBreakpoints(shouldDisableBreakpoints) {
+	  return _ref6 => {
+	    var dispatch = _ref6.dispatch;
+	    var getState = _ref6.getState;
+	
+	    var breakpoints = getBreakpoints(getState());
+	    return dispatch({
+	      type: constants.TOGGLE_BREAKPOINTS,
+	      shouldDisableBreakpoints,
+	      [PROMISE]: _asyncToGenerator(function* () {
+	        for (var _ref8 of breakpoints) {
+	          var _ref9 = _slicedToArray(_ref8, 2);
+	
+	          var breakpoint = _ref9[1];
+	
+	          if (shouldDisableBreakpoints) {
+	            yield dispatch(disableBreakpoint(breakpoint.location));
+	          } else {
+	            yield dispatch(enableBreakpoint(breakpoint.location));
+	          }
+	        }
+	      })()
+	    });
+	  };
+	}
+	
+	/**
+	 * Update the condition of a breakpoint.
+	 *  **NOT IMPLEMENTED**
+	 *
+	 * @throws {Error} "not implemented"
+	 * @memberof actions/breakpoints
+	 * @static
+	 * @param {Location} location
+	 *        @see DebuggerController.Breakpoints.addBreakpoint
+	 * @param {string} condition
+	 *        The condition to set on the breakpoint
+	 */
+	function setBreakpointCondition(location, condition) {
+	  throw new Error("not implemented");
+	
+	  // return ({ dispatch, getState, client }) => {
+	  //   const bp = getBreakpoint(getState(), location);
+	  //   if (!bp) {
+	  //     throw new Error("Breakpoint does not exist at the specified location");
+	  //   }
+	  //   if (bp.get("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 dispatch({
+	  //     type: constants.SET_BREAKPOINT_CONDITION,
+	  //     breakpoint: bp,
+	  //     condition: condition,
+	  //     [PROMISE]: Task.spawn(function* () {
+	  //       yield client.setBreakpointCondition(bp.get("id"), condition);
+	  //     })
+	  //   });
+	  // };
+	}
+	
+	module.exports = {
+	  enableBreakpoint,
+	  addBreakpoint,
+	  disableBreakpoint,
+	  removeBreakpoint,
+	  toggleAllBreakpoints,
+	  setBreakpointCondition
+	};
+
+/***/ },
+/* 211 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var _fetchSourceMap = (() => {
+	  var _ref = _asyncToGenerator(function* (generatedSource) {
+	    // Fetch the sourcemap over the network and create it.
+	    var sourceMapURL = _resolveSourceMapURL(generatedSource);
+	    var fetched = yield networkRequest(sourceMapURL, { loadFromCache: false });
+	
+	    // Create the source map and fix it up.
+	    var map = new SourceMapConsumer(fetched.content);
+	    _setSourceMapRoot(map, sourceMapURL, generatedSource);
+	    return map;
+	  });
+	
+	  return function _fetchSourceMap(_x) {
+	    return _ref.apply(this, arguments);
+	  };
+	})();
+	
+	var getGeneratedLocation = (() => {
+	  var _ref2 = _asyncToGenerator(function* (location, state) {
+	    if (!isOriginalId(location.sourceId)) {
+	      return location;
+	    }
+	
+	    var originalSource = getSource(state, location.sourceId).toJS();
+	    var generatedSourceId = originalToGeneratedId(location.sourceId);
+	    var map = yield getSourceMap(generatedSourceId);
+	    if (!map) {
+	      return location;
+	    }
+	
+	    var _map$generatedPositio = map.generatedPositionFor({
+	      source: originalSource.url,
+	      line: location.line,
+	      column: location.column == null ? 0 : location.column
+	    });
+	
+	    var line = _map$generatedPositio.line;
+	    var column = _map$generatedPositio.column;
+	
+	
+	    return {
+	      sourceId: generatedSourceId,
+	      line: line,
+	      // Treat 0 as no column so that line breakpoints work correctly.
+	      column: column === 0 ? undefined : column
+	    };
+	  });
+	
+	  return function getGeneratedLocation(_x2, _x3) {
+	    return _ref2.apply(this, arguments);
+	  };
+	})();
+	
+	var getOriginalLocation = (() => {
+	  var _ref3 = _asyncToGenerator(function* (location) {
+	    if (!isGeneratedId(location.sourceId)) {
+	      return location;
+	    }
+	
+	    var map = yield getSourceMap(location.sourceId);
+	    if (!map) {
+	      return location;
+	    }
+	
+	    var _map$originalPosition = map.originalPositionFor({
+	      line: location.line,
+	      column: location.column == null ? Infinity : location.column
+	    });
+	
+	    var url = _map$originalPosition.source;
+	    var line = _map$originalPosition.line;
+	    var column = _map$originalPosition.column;
+	
+	
+	    if (url == null) {
+	      // No url means the location didn't map.
+	      return location;
+	    }
+	
+	    return {
+	      sourceId: generatedToOriginalId(location.sourceId, url),
+	      line,
+	      column
+	    };
+	  });
+	
+	  return function getOriginalLocation(_x4) {
+	    return _ref3.apply(this, arguments);
+	  };
+	})();
+	
+	var getOriginalSourceText = (() => {
+	  var _ref4 = _asyncToGenerator(function* (originalSource) {
+	    assert(isOriginalId(originalSource.id), "Source is not an original source");
+	
+	    var generatedSourceId = originalToGeneratedId(originalSource.id);
+	    var map = yield getSourceMap(generatedSourceId);
+	    if (!map) {
+	      return null;
+	    }
+	
+	    var text = map.sourceContentFor(originalSource.url);
+	    if (!text) {
+	      text = (yield networkRequest(originalSource.url, { loadFromCache: false })).content;
+	    }
+	
+	    return {
+	      text,
+	      contentType: isJavaScript(originalSource.url) ? "text/javascript" : "text/plain"
+	    };
+	  });
+	
+	  return function getOriginalSourceText(_x5) {
+	    return _ref4.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) { return step("next", value); }, function (err) { return step("throw", err); }); } } return step("next"); }); }; }
+	
+	var URL = __webpack_require__(212);
+	var md5 = __webpack_require__(217);
+	
+	var _require = __webpack_require__(221);
+	
+	var SourceMapConsumer = _require.SourceMapConsumer;
+	var SourceMapGenerator = _require.SourceMapGenerator;
+	
+	var path = __webpack_require__(232);
+	var networkRequest = __webpack_require__(175);
+	
+	var _require2 = __webpack_require__(199);
+	
+	var getSource = _require2.getSource;
+	
+	var _require3 = __webpack_require__(46);
+	
+	var isEnabled = _require3.isEnabled;
+	
+	var _require4 = __webpack_require__(233);
+	
+	var isJavaScript = _require4.isJavaScript;
+	
+	var assert = __webpack_require__(186);
+	
+	var sourceMapRequests = new Map();
+	
+	function clearSourceMaps() {
+	  sourceMapRequests = new Map();
+	}
+	
+	function _resolveSourceMapURL(source) {
+	  if (path.isURL(source.sourceMapURL) || !source.url) {
+	    // If it's already a full URL or the source doesn't have a URL,
+	    // don't resolve anything.
+	    return source.sourceMapURL;
+	  } else if (path.isAbsolute(source.sourceMapURL)) {
+	    // If it's an absolute path, it should be resolved relative to the
+	    // host of the source.
+	    var urlObj = URL.parse(source.url);
+	    var base = urlObj.protocol + "//" + urlObj.host;
+	    return base + source.sourceMapURL;
+	  }
+	  // Otherwise, it's a relative path and should be resolved relative
+	  // to the source.
+	  return path.dirname(source.url) + "/" + source.sourceMapURL;
+	}
+	
+	/**
+	 * Sets the source map's sourceRoot to be relative to the source map url.
+	 */
+	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;
+	  }
+	
+	  var base = path.dirname(absSourceMapURL.indexOf("data:") === 0 && source.url ? source.url : absSourceMapURL);
+	
+	  if (sourceMap.sourceRoot) {
+	    sourceMap.sourceRoot = path.join(base, sourceMap.sourceRoot);
+	  } else {
+	    sourceMap.sourceRoot = base;
+	  }
+	
+	  return sourceMap;
+	}
+	
+	function originalToGeneratedId(originalId) {
+	  var match = originalId.match(/(.*)\/originalSource/);
+	  return match ? match[1] : null;
+	}
+	
+	function generatedToOriginalId(generatedId, url) {
+	  return generatedId + "/originalSource-" + md5(url);
+	}
+	
+	function isOriginalId(id) {
+	  return id.match(/\/originalSource/);
+	}
+	
+	function isGeneratedId(id) {
+	  return !isOriginalId(id);
+	}
+	
+	function fetchSourceMap(generatedSource) {
+	  var existingRequest = sourceMapRequests.get(generatedSource.id);
+	
+	  if (!generatedSource.sourceMapURL || !isEnabled("sourceMaps")) {
+	    return Promise.resolve(null);
+	  } else if (existingRequest) {
+	    // If it has already been requested, return the request. 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;
+	  }
+	
+	  // Fire off the request, set it in the cache, and return it.
+	  var req = _fetchSourceMap(generatedSource);
+	  sourceMapRequests.set(generatedSource.id, req);
+	  return req;
+	}
+	
+	function getSourceMap(generatedSourceId) {
+	  return sourceMapRequests.get(generatedSourceId);
+	}
+	
+	function applySourceMap(generatedId, url, code, mappings) {
+	  var generator = new SourceMapGenerator({ file: url });
+	  mappings.forEach(mapping => generator.addMapping(mapping));
+	  generator.setSourceContent(url, code);
+	
+	  var map = SourceMapConsumer(generator.toJSON());
+	  sourceMapRequests.set(generatedId, Promise.resolve(map));
+	  return map;
+	}
+	
+	module.exports = {
+	  originalToGeneratedId,
+	  generatedToOriginalId,
+	  isGeneratedId,
+	  isOriginalId,
+	
+	  fetchSourceMap,
+	  getGeneratedLocation,
+	  getOriginalLocation,
+	  getOriginalSourceText,
+	  applySourceMap,
+	  clearSourceMaps
+	};
+
+/***/ },
+/* 212 */
+/***/ function(module, exports, __webpack_require__) {
+
 	// Copyright Joyent, Inc. and other Node contributors.
 	//
 	// Permission is hereby granted, free of charge, to any person obtaining a
 	// copy of this software and associated documentation files (the
 	// "Software"), to deal in the Software without restriction, including
 	// without limitation the rights to use, copy, modify, merge, publish,
 	// distribute, sublicense, and/or sell copies of the Software, and to permit
 	// persons to whom the Software is furnished to do so, subject to the
@@ -27147,17 +28569,17 @@ var Debugger =
 	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
 	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 	// USE OR OTHER DEALINGS IN THE SOFTWARE.
 	
-	var punycode = __webpack_require__(201);
+	var punycode = __webpack_require__(213);
 	
 	exports.parse = urlParse;
 	exports.resolve = urlResolve;
 	exports.resolveObject = urlResolveObject;
 	exports.format = urlFormat;
 	
 	exports.Url = Url;
 	
@@ -27219,17 +28641,17 @@ var Debugger =
 	      'gopher': true,
 	      'file': true,
 	      'http:': true,
 	      'https:': true,
 	      'ftp:': true,
 	      'gopher:': true,
 	      'file:': true
 	    },
-	    querystring = __webpack_require__(202);
+	    querystring = __webpack_require__(214);
 	
 	function urlParse(url, parseQueryString, slashesDenoteHost) {
 	  if (url && isObject(url) && url instanceof Url) return url;
 	
 	  var u = new Url;
 	  u.parse(url, parseQueryString, slashesDenoteHost);
 	  return u;
 	}
@@ -27836,17 +29258,17 @@ var Debugger =
 	  return arg === null;
 	}
 	function isNullOrUndefined(arg) {
 	  return  arg == null;
 	}
 
 
 /***/ },
-/* 201 */
+/* 213 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/punycode v1.3.2 by @mathias */
 	;(function(root) {
 	
 		/** Detect free variables */
 		var freeExports = typeof exports == 'object' && exports &&
 			!exports.nodeType && exports;
@@ -28371,27 +29793,27 @@ var Debugger =
 			root.punycode = punycode;
 		}
 	
 	}(this));
 	
 	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(101)(module), (function() { return this; }())))
 
 /***/ },
-/* 202 */
+/* 214 */
 /***/ function(module, exports, __webpack_require__) {
 
 	'use strict';
 	
-	exports.decode = exports.parse = __webpack_require__(203);
-	exports.encode = exports.stringify = __webpack_require__(204);
-
-
-/***/ },
-/* 203 */
+	exports.decode = exports.parse = __webpack_require__(215);
+	exports.encode = exports.stringify = __webpack_require__(216);
+
+
+/***/ },
+/* 215 */
 /***/ function(module, exports) {
 
 	// Copyright Joyent, Inc. and other Node contributors.
 	//
 	// Permission is hereby granted, free of charge, to any person obtaining a
 	// copy of this software and associated documentation files (the
 	// "Software"), to deal in the Software without restriction, including
 	// without limitation the rights to use, copy, modify, merge, publish,
@@ -28467,17 +29889,17 @@ var Debugger =
 	    }
 	  }
 	
 	  return obj;
 	};
 
 
 /***/ },
-/* 204 */
+/* 216 */
 /***/ function(module, exports) {
 
 	// Copyright Joyent, Inc. and other Node contributors.
 	//
 	// Permission is hereby granted, free of charge, to any person obtaining a
 	// copy of this software and associated documentation files (the
 	// "Software"), to deal in the Software without restriction, including
 	// without limitation the rights to use, copy, modify, merge, publish,
@@ -28537,17 +29959,3346 @@ var Debugger =
 	
 	  if (!name) return '';
 	  return encodeURIComponent(stringifyPrimitive(name)) + eq +
 	         encodeURIComponent(stringifyPrimitive(obj));
 	};
 
 
 /***/ },
-/* 205 */
+/* 217 */
+/***/ function(module, exports, __webpack_require__) {
+
+	(function(){
+	  var crypt = __webpack_require__(218),
+	      utf8 = __webpack_require__(219).utf8,
+	      isBuffer = __webpack_require__(220),
+	      bin = __webpack_require__(219).bin,
+	
+	  // The core
+	  md5 = function (message, options) {
+	    // Convert to byte array
+	    if (message.constructor == String)
+	      if (options && options.encoding === 'binary')
+	        message = bin.stringToBytes(message);
+	      else
+	        message = utf8.stringToBytes(message);
+	    else if (isBuffer(message))
+	      message = Array.prototype.slice.call(message, 0);
+	    else if (!Array.isArray(message))
+	      message = message.toString();
+	    // else, assume byte array already
+	
+	    var m = crypt.bytesToWords(message),
+	        l = message.length * 8,
+	        a =  1732584193,
+	        b = -271733879,
+	        c = -1732584194,
+	        d =  271733878;
+	
+	    // Swap endian
+	    for (var i = 0; i < m.length; i++) {
+	      m[i] = ((m[i] <<  8) | (m[i] >>> 24)) & 0x00FF00FF |
+	             ((m[i] << 24) | (m[i] >>>  8)) & 0xFF00FF00;
+	    }
+	
+	    // Padding
+	    m[l >>> 5] |= 0x80 << (l % 32);
+	    m[(((l + 64) >>> 9) << 4) + 14] = l;
+	
+	    // Method shortcuts
+	    var FF = md5._ff,
+	        GG = md5._gg,
+	        HH = md5._hh,
+	        II = md5._ii;
+	
+	    for (var i = 0; i < m.length; i += 16) {
+	
+	      var aa = a,
+	          bb = b,
+	          cc = c,
+	          dd = d;
+	
+	      a = FF(a, b, c, d, m[i+ 0],  7, -680876936);
+	      d = FF(d, a, b, c, m[i+ 1], 12, -389564586);
+	      c = FF(c, d, a, b, m[i+ 2], 17,  606105819);
+	      b = FF(b, c, d, a, m[i+ 3], 22, -1044525330);
+	      a = FF(a, b, c, d, m[i+ 4],  7, -176418897);
+	      d = FF(d, a, b, c, m[i+ 5], 12,  1200080426);
+	      c = FF(c, d, a, b, m[i+ 6], 17, -1473231341);
+	      b = FF(b, c, d, a, m[i+ 7], 22, -45705983);
+	      a = FF(a, b, c, d, m[i+ 8],  7,  1770035416);
+	      d = FF(d, a, b, c, m[i+ 9], 12, -1958414417);
+	      c = FF(c, d, a, b, m[i+10], 17, -42063);
+	      b = FF(b, c, d, a, m[i+11], 22, -1990404162);
+	      a = FF(a, b, c, d, m[i+12],  7,  1804603682);
+	      d = FF(d, a, b, c, m[i+13], 12, -40341101);
+	      c = FF(c, d, a, b, m[i+14], 17, -1502002290);
+	      b = FF(b, c, d, a, m[i+15], 22,  1236535329);
+	
+	      a = GG(a, b, c, d, m[i+ 1],  5, -165796510);
+	      d = GG(d, a, b, c, m[i+ 6],  9, -1069501632);
+	      c = GG(c, d, a, b, m[i+11], 14,  643717713);
+	      b = GG(b, c, d, a, m[i+ 0], 20, -373897302);
+	      a = GG(a, b, c, d, m[i+ 5],  5, -701558691);
+	      d = GG(d, a, b, c, m[i+10],  9,  38016083);
+	      c = GG(c, d, a, b, m[i+15], 14, -660478335);
+	      b = GG(b, c, d, a, m[i+ 4], 20, -405537848);
+	      a = GG(a, b, c, d, m[i+ 9],  5,  568446438);
+	      d = GG(d, a, b, c, m[i+14],  9, -1019803690);
+	      c = GG(c, d, a, b, m[i+ 3], 14, -187363961);
+	      b = GG(b, c, d, a, m[i+ 8], 20,  1163531501);
+	      a = GG(a, b, c, d, m[i+13],  5, -1444681467);
+	      d = GG(d, a, b, c, m[i+ 2],  9, -51403784);
+	      c = GG(c, d, a, b, m[i+ 7], 14,  1735328473);
+	      b = GG(b, c, d, a, m[i+12], 20, -1926607734);
+	
+	      a = HH(a, b, c, d, m[i+ 5],  4, -378558);
+	      d = HH(d, a, b, c, m[i+ 8], 11, -2022574463);
+	      c = HH(c, d, a, b, m[i+11], 16,  1839030562);
+	      b = HH(b, c, d, a, m[i+14], 23, -35309556);
+	      a = HH(a, b, c, d, m[i+ 1],  4, -1530992060);
+	      d = HH(d, a, b, c, m[i+ 4], 11,  1272893353);
+	      c = HH(c, d, a, b, m[i+ 7], 16, -155497632);
+	      b = HH(b, c, d, a, m[i+10], 23, -1094730640);
+	      a = HH(a, b, c, d, m[i+13],  4,  681279174);
+	      d = HH(d, a, b, c, m[i+ 0], 11, -358537222);
+	      c = HH(c, d, a, b, m[i+ 3], 16, -722521979);
+	      b = HH(b, c, d, a, m[i+ 6], 23,  76029189);
+	      a = HH(a, b, c, d, m[i+ 9],  4, -640364487);
+	      d = HH(d, a, b, c, m[i+12], 11, -421815835);
+	      c = HH(c, d, a, b, m[i+15], 16,  530742520);
+	      b = HH(b, c, d, a, m[i+ 2], 23, -995338651);
+	
+	      a = II(a, b, c, d, m[i+ 0],  6, -198630844);
+	      d = II(d, a, b, c, m[i+ 7], 10,  1126891415);
+	      c = II(c, d, a, b, m[i+14], 15, -1416354905);
+	      b = II(b, c, d, a, m[i+ 5], 21, -57434055);
+	      a = II(a, b, c, d, m[i+12],  6,  1700485571);
+	      d = II(d, a, b, c, m[i+ 3], 10, -1894986606);
+	      c = II(c, d, a, b, m[i+10], 15, -1051523);
+	      b = II(b, c, d, a, m[i+ 1], 21, -2054922799);
+	      a = II(a, b, c, d, m[i+ 8],  6,  1873313359);
+	      d = II(d, a, b, c, m[i+15], 10, -30611744);
+	      c = II(c, d, a, b, m[i+ 6], 15, -1560198380);
+	      b = II(b, c, d, a, m[i+13], 21,  1309151649);
+	      a = II(a, b, c, d, m[i+ 4],  6, -145523070);
+	      d = II(d, a, b, c, m[i+11], 10, -1120210379);
+	      c = II(c, d, a, b, m[i+ 2], 15,  718787259);
+	      b = II(b, c, d, a, m[i+ 9], 21, -343485551);
+	
+	      a = (a + aa) >>> 0;
+	      b = (b + bb) >>> 0;
+	      c = (c + cc) >>> 0;
+	      d = (d + dd) >>> 0;
+	    }
+	
+	    return crypt.endian([a, b, c, d]);
+	  };
+	
+	  // Auxiliary functions
+	  md5._ff  = function (a, b, c, d, x, s, t) {
+	    var n = a + (b & c | ~b & d) + (x >>> 0) + t;
+	    return ((n << s) | (n >>> (32 - s))) + b;
+	  };
+	  md5._gg  = function (a, b, c, d, x, s, t) {
+	    var n = a + (b & d | c & ~d) + (x >>> 0) + t;
+	    return ((n << s) | (n >>> (32 - s))) + b;
+	  };
+	  md5._hh  = function (a, b, c, d, x, s, t) {
+	    var n = a + (b ^ c ^ d) + (x >>> 0) + t;
+	    return ((n << s) | (n >>> (32 - s))) + b;
+	  };
+	  md5._ii  = function (a, b, c, d, x, s, t) {
+	    var n = a + (c ^ (b | ~d)) + (x >>> 0) + t;
+	    return ((n << s) | (n >>> (32 - s))) + b;
+	  };
+	
+	  // Package private blocksize
+	  md5._blocksize = 16;
+	  md5._digestsize = 16;
+	
+	  module.exports = function (message, options) {
+	    if (message === undefined || message === null)
+	      throw new Error('Illegal argument ' + message);
+	
+	    var digestbytes = crypt.wordsToBytes(md5(message, options));
+	    return options && options.asBytes ? digestbytes :
+	        options && options.asString ? bin.bytesToString(digestbytes) :
+	        crypt.bytesToHex(digestbytes);
+	  };
+	
+	})();
+
+
+/***/ },
+/* 218 */
+/***/ function(module, exports) {
+
+	(function() {
+	  var base64map
+	      = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
+	
+	  crypt = {
+	    // Bit-wise rotation left
+	    rotl: function(n, b) {
+	      return (n << b) | (n >>> (32 - b));
+	    },
+	
+	    // Bit-wise rotation right
+	    rotr: function(n, b) {
+	      return (n << (32 - b)) | (n >>> b);
+	    },
+	
+	    // Swap big-endian to little-endian and vice versa
+	    endian: function(n) {
+	      // If number given, swap endian
+	      if (n.constructor == Number) {
+	        return crypt.rotl(n, 8) & 0x00FF00FF | crypt.rotl(n, 24) & 0xFF00FF00;
+	      }
+	
+	      // Else, assume array and swap all items
+	      for (var i = 0; i < n.length; i++)
+	        n[i] = crypt.endian(n[i]);
+	      return n;
+	    },
+	
+	    // Generate an array of any length of random bytes
+	    randomBytes: function(n) {
+	      for (var bytes = []; n > 0; n--)
+	        bytes.push(Math.floor(Math.random() * 256));
+	      return bytes;
+	    },
+	
+	    // Convert a byte array to big-endian 32-bit words
+	    bytesToWords: function(bytes) {
+	      for (var words = [], i = 0, b = 0; i < bytes.length; i++, b += 8)
+	        words[b >>> 5] |= bytes[i] << (24 - b % 32);
+	      return words;
+	    },
+	
+	    // Convert big-endian 32-bit words to a byte array
+	    wordsToBytes: function(words) {
+	      for (var bytes = [], b = 0; b < words.length * 32; b += 8)
+	        bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF);
+	      return bytes;
+	    },
+	
+	    // Convert a byte array to a hex string
+	    bytesToHex: function(bytes) {
+	      for (var hex = [], i = 0; i < bytes.length; i++) {
+	        hex.push((bytes[i] >>> 4).toString(16));
+	        hex.push((bytes[i] & 0xF).toString(16));
+	      }
+	      return hex.join('');
+	    },
+	
+	    // Convert a hex string to a byte array
+	    hexToBytes: function(hex) {
+	      for (var bytes = [], c = 0; c < hex.length; c += 2)
+	        bytes.push(parseInt(hex.substr(c, 2), 16));
+	      return bytes;
+	    },
+	
+	    // Convert a byte array to a base-64 string
+	    bytesToBase64: function(bytes) {
+	      for (var base64 = [], i = 0; i < bytes.length; i += 3) {
+	        var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
+	        for (var j = 0; j < 4; j++)
+	          if (i * 8 + j * 6 <= bytes.length * 8)
+	            base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F));
+	          else
+	            base64.push('=');
+	      }
+	      return base64.join('');
+	    },
+	
+	    // Convert a base-64 string to a byte array
+	    base64ToBytes: function(base64) {
+	      // Remove non-base-64 characters
+	      base64 = base64.replace(/[^A-Z0-9+\/]/ig, '');
+	
+	      for (var bytes = [], i = 0, imod4 = 0; i < base64.length;
+	          imod4 = ++i % 4) {
+	        if (imod4 == 0) continue;
+	        bytes.push(((base64map.indexOf(base64.charAt(i - 1))
+	            & (Math.pow(2, -2 * imod4 + 8) - 1)) << (imod4 * 2))
+	            | (base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2)));
+	      }
+	      return bytes;
+	    }
+	  };
+	
+	  module.exports = crypt;
+	})();
+
+
+/***/ },
+/* 219 */
+/***/ function(module, exports) {
+
+	var charenc = {
+	  // UTF-8 encoding
+	  utf8: {
+	    // Convert a string to a byte array
+	    stringToBytes: function(str) {
+	      return charenc.bin.stringToBytes(unescape(encodeURIComponent(str)));
+	    },
+	
+	    // Convert a byte array to a string
+	    bytesToString: function(bytes) {
+	      return decodeURIComponent(escape(charenc.bin.bytesToString(bytes)));
+	    }
+	  },
+	
+	  // Binary encoding
+	  bin: {
+	    // Convert a string to a byte array
+	    stringToBytes: function(str) {
+	      for (var bytes = [], i = 0; i < str.length; i++)
+	        bytes.push(str.charCodeAt(i) & 0xFF);
+	      return bytes;
+	    },
+	
+	    // Convert a byte array to a string
+	    bytesToString: function(bytes) {
+	      for (var str = [], i = 0; i < bytes.length; i++)
+	        str.push(String.fromCharCode(bytes[i]));
+	      return str.join('');
+	    }
+	  }
+	};
+	
+	module.exports = charenc;
+
+
+/***/ },
+/* 220 */
+/***/ function(module, exports) {
+
+	/**
+	 * Determine if an object is Buffer
+	 *
+	 * Author:   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
+	 * License:  MIT
+	 *
+	 * `npm install is-buffer`
+	 */
+	
+	module.exports = function (obj) {
+	  return !!(obj != null &&
+	    (obj._isBuffer || // For Safari 5-7 (missing Object.prototype.constructor)
+	      (obj.constructor &&
+	      typeof obj.constructor.isBuffer === 'function' &&
+	      obj.constructor.isBuffer(obj))
+	    ))
+	}
+
+
+/***/ },
+/* 221 */
+/***/ 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__(222).SourceMapGenerator;
+	exports.SourceMapConsumer = __webpack_require__(228).SourceMapConsumer;
+	exports.SourceNode = __webpack_require__(231).SourceNode;
+
+
+/***/ },
+/* 222 */
+/***/ 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__(223);
+	var util = __webpack_require__(225);
+	var ArraySet = __webpack_require__(226).ArraySet;
+	var MappingList = __webpack_require__(227).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) {
+	    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;
+
+
+/***/ },
+/* 223 */
+/***/ 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__(224);
+	
+	// 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;
+	};
+
+
+/***/ },
+/* 224 */
+/***/ 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;
+	};
+
+
+/***/ },
+/* 225 */
+/***/ 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;
+
+
+/***/ },
+/* 226 */
+/***/ 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__(225);
+	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.
+	 */
+	function ArraySet() {
+	  this._array = [];
+	  this._set = 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 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 = util.toSetString(aStr);
+	  var isDuplicate = has.call(this._set, sStr);
+	  var idx = this._array.length;
+	  if (!isDuplicate || aAllowDuplicates) {
+	    this._array.push(aStr);
+	  }
+	  if (!isDuplicate) {
+	    this._set[sStr] = idx;
+	  }
+	};
+	
+	/**
+	 * Is the given string a member of this set?
+	 *
+	 * @param String aStr
+	 */
+	ArraySet.prototype.has = function ArraySet_has(aStr) {
+	  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) {
+	  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;
+
+
+/***/ },
+/* 227 */
+/***/ 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__(225);
+	
+	/**
+	 * 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;
+
+
+/***/ },
+/* 228 */
+/***/ 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__(225);
+	var binarySearch = __webpack_require__(229);
+	var ArraySet = __webpack_require__(226).ArraySet;
+	var base64VLQ = __webpack_require__(223);
+	var quickSort = __webpack_require__(230).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;
+
+
+/***/ },
+/* 229 */
+/***/ 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;
+	};
+
+
+/***/ },
+/* 230 */
+/***/ 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);
+	};
+
+
+/***/ },
+/* 231 */
+/***/ 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__(222).SourceMapGenerator;
+	var util = __webpack_require__(225);
+	
+	// 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 removed from this array, by calling `shiftNextLine`.
+	    var remainingLines = aGeneratedCode.split(REGEX_NEWLINE);
+	    var shiftNextLine = function() {
+	      var lineContents = remainingLines.shift();
+	      // The last line of a file might not have a newline.
+	      var newLine = remainingLines.shift() || "";
+	      return lineContents + newLine;
+	    };
+	
+	    // 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[0];
+	          var code = nextLine.substr(0, mapping.generatedColumn -
+	                                        lastGeneratedColumn);
+	          remainingLines[0] = 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[0];
+	        node.add(nextLine.substr(0, mapping.generatedColumn));
+	        remainingLines[0] = nextLine.substr(mapping.generatedColumn);
+	        lastGeneratedColumn = mapping.generatedColumn;
+	      }
+	      lastMapping = mapping;
+	    }, this);
+	    // We have processed all mappings.
+	    if (remainingLines.length > 0) {
+	      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.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;
+
+
+/***/ },
+/* 232 */
 /***/ function(module, exports) {
 
 	function basename(path) {
 	  return path.split("/").pop();
 	}
 	
 	function dirname(path) {
 	  var idx = path.lastIndexOf("/");
@@ -28562,1422 +33313,79 @@ var Debugger =
 	  return str[0] === "/";
 	}
 	
 	module.exports = {
 	  basename, dirname, isURL, isAbsolute
 	};
 
 /***/ },
-/* 206 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var React = __webpack_require__(17);
-	
-	var _require = __webpack_require__(15);
-	
-	var connect = _require.connect;
-	
-	var classnames = __webpack_require__(207);
-	
-	var _require2 = __webpack_require__(199);
-	
-	var getTabs = _require2.getTabs;
-	
-	
-	__webpack_require__(208);
-	var dom = React.DOM;
-	
-	var githubUrl = "https://github.com/devtools-html/debugger.html/blob/master";
-	
-	function getTabsByBrowser(tabs, browser) {
-	  return tabs.valueSeq().filter(tab => tab.get("browser") == browser);
-	}
-	
-	function renderTabs(tabTitle, tabs, paramName) {
-	  if (tabs.count() == 0) {
-	    return null;
-	  }
-	
-	  return dom.div({ className: `tab-group ${ tabTitle }` }, dom.div({ className: "tab-group-title" }, tabTitle), dom.ul({ className: "tab-list" }, tabs.valueSeq().map(tab => dom.li({ "className": "tab",
-	    "key": tab.get("id"),
-	    "onClick": () => {
-	      window.location = "/?" + paramName + "=" + tab.get("id");
-	    } }, dom.div({ className: "tab-title" }, tab.get("title")), dom.div({ className: "tab-url" }, tab.get("url"))))));
-	}
-	
-	function renderMessage(noTabs) {
-	  return dom.div({ className: classnames("connect-message", { "not-connected": noTabs }) }, dom.p(null, noTabs && "No remote tabs found. ", "You may be looking to ", dom.a({
-	    href: `/?ws=${ document.location.hostname }:9229/node`
-	  }, "connect to Node"), "."), dom.p(null, "Make sure you run ", dom.a({ href: `${ githubUrl }/CONTRIBUTING.md#firefox` }, "Firefox"), ", ", dom.a({ href: `${ githubUrl }/CONTRIBUTING.md#chrome` }, "Chrome"), " or ", dom.a({ href: `${ githubUrl }/CONTRIBUTING.md#nodejs` }, "Node"), " with the right flags."));
-	}
-	function Tabs(_ref) {
-	  var tabs = _ref.tabs;
-	
-	  var firefoxTabs = getTabsByBrowser(tabs, "firefox");
-	  var chromeTabs = getTabsByBrowser(tabs, "chrome");
-	
-	  return dom.div({ className: "tabs theme-light" }, renderTabs("Firefox Tabs", firefoxTabs, "firefox-tab"), renderTabs("Chrome Tabs", chromeTabs, "chrome-tab"), renderMessage(tabs.isEmpty()));
-	}
-	
-	module.exports = connect(state => ({ tabs: getTabs(state) }))(Tabs);
-
-/***/ },
-/* 207 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
-	  Copyright (c) 2016 Jed Watson.
-	  Licensed under the MIT License (MIT), see
-	  http://jedwatson.github.io/classnames
-	*/
-	/* global define */
-	
-	(function () {
-		'use strict';
-	
-		var hasOwn = {}.hasOwnProperty;
-	
-		function classNames () {
-			var classes = [];
-	
-			for (var i = 0; i < arguments.length; i++) {
-				var arg = arguments[i];
-				if (!arg) continue;
-	
-				var argType = typeof arg;
-	
-				if (argType === 'string' || argType === 'number') {
-					classes.push(arg);
-				} else if (Array.isArray(arg)) {
-					classes.push(classNames.apply(null, arg));
-				} else if (argType === 'object') {
-					for (var key in arg) {
-						if (hasOwn.call(arg, key) && arg[key]) {
-							classes.push(key);
-						}
-					}
-				}
-			}
-	
-			return classes.join(' ');
-		}
-	
-		if (typeof module !== 'undefined' && module.exports) {
-			module.exports = classNames;
-		} else if (true) {
-			// register as 'classnames', consistent with npm package name
-			!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = function () {
-				return classNames;
-			}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
-		} else {
-			window.classNames = classNames;
-		}
-	}());
-
-
-/***/ },
-/* 208 */
-/***/ function(module, exports) {
-
-	// removed by extract-text-webpack-plugin
-
-/***/ },
-/* 209 */,
-/* 210 */,
-/* 211 */,
-/* 212 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var React = __webpack_require__(17);
-	var dom = React.DOM;
-	var PropTypes = React.PropTypes;
-	var createFactory = React.createFactory;
-	
-	var _require = __webpack_require__(15);
-	
-	var connect = _require.connect;
-	
-	var _require2 = __webpack_require__(2);
-	
-	var bindActionCreators = _require2.bindActionCreators;
-	
-	var _require3 = __webpack_require__(213);
-	
-	var Services = _require3.Services;
-	
-	var classnames = __webpack_require__(207);
-	var actions = __webpack_require__(214);
-	
-	var _require4 = __webpack_require__(46);
-	
-	var isFirefoxPanel = _require4.isFirefoxPanel;
-	
-	
-	__webpack_require__(225);
-	
-	// Using this static variable allows webpack to know at compile-time
-	// to avoid this require and not include it at all in the output.
-	if (false) {
-	  require("../lib/themes/light-theme.css");
-	}
-	
-	var Sources = createFactory(__webpack_require__(227));
-	var Editor = createFactory(__webpack_require__(262));
-	var SplitBox = createFactory(__webpack_require__(267));
-	var RightSidebar = createFactory(__webpack_require__(271));
-	var SourceTabs = createFactory(__webpack_require__(348));
-	var SourceFooter = createFactory(__webpack_require__(353));
-	var Svg = __webpack_require__(235);
-	var Autocomplete = createFactory(__webpack_require__(356));
-	
-	var _require5 = __webpack_require__(199);
-	
-	var getSources = _require5.getSources;
-	var getSelectedSource = _require5.getSelectedSource;
-	
-	var _require6 = __webpack_require__(176);
-	
-	var endTruncateStr = _require6.endTruncateStr;
-	
-	var _require7 = __webpack_require__(365);
-	
-	var KeyShortcuts = _require7.KeyShortcuts;
-	
-	var _require8 = __webpack_require__(230);
-	
-	var isHiddenSource = _require8.isHiddenSource;
-	var getURL = _require8.getURL;
-	
-	
-	function searchResults(sources) {
-	  function getSourcePath(source) {
-	    var _getURL = getURL(source);
-	
-	    var path = _getURL.path;
-	
-	    return endTruncateStr(path, 50);
-	  }
-	
-	  return sources.valueSeq().filter(source => !isHiddenSource(source)).map(source => ({
-	    value: getSourcePath(source),
-	    title: getSourcePath(source).split("/").pop(),
-	    subtitle: getSourcePath(source),
-	    id: source.get("id")
-	  })).toJS();
-	}
-	
-	var App = React.createClass({
-	  propTypes: {
-	    sources: PropTypes.object,
-	    selectSource: PropTypes.func,
-	    selectedSource: PropTypes.object
-	  },
-	
-	  displayName: "App",
-	
-	  getInitialState() {
-	    return {
-	      searchOn: false
-	    };
-	  },
-	
-	  componentDidMount() {
-	    this.shortcuts = new KeyShortcuts({ window });
-	    this.shortcuts.on("CmdOrCtrl+P", this.toggleSourcesSearch);
-	    window.addEventListener("keydown", this.onKeyDown);
-	  },
-	
-	  componentWillUnmount() {
-	    this.shortcuts.off("CmdOrCtrl+P", this.toggleSourcesSearch);
-	    window.removeEventListener("keydown", this.onKeyDown);
-	  },
-	
-	  toggleSourcesSearch(key, e) {
-	    e.preventDefault();
-	    this.setState({ searchOn: !this.state.searchOn });
-	  },
-	
-	  onKeyDown(e) {
-	    if (this.state.searchOn && e.key === "Escape") {
-	      this.setState({ searchOn: false });
-	      e.preventDefault();
-	    }
-	  },
-	
-	  closeSourcesSearch() {
-	    this.setState({ searchOn: false });
-	  },
-	
-	  renderSourcesSearch() {
-	    return dom.div({ className: "search-container" }, Autocomplete({
-	      selectItem: result => {
-	        this.props.selectSource(result.id);
-	        this.setState({ searchOn: false });
-	      },
-	      items: searchResults(this.props.sources)
-	    }), dom.div({ className: "close-button" }, Svg("close", { onClick: this.closeSourcesSearch })));
-	  },
-	
-	  renderWelcomeBox() {
-	    var modifierTxt = Services.appinfo.OS === "Darwin" ? "Cmd" : "Ctrl";
-	    return dom.div({ className: "welcomebox" }, `Want to find a file? (${ modifierTxt } + P)`);
-	  },
-	
-	  renderCenterPane() {
-	    return dom.div({ className: "center-pane" }, dom.div({ className: "editor-container" }, SourceTabs(), Editor(), !this.props.selectedSource ? this.renderWelcomeBox() : null, this.state.searchOn ? this.renderSourcesSearch() : null, SourceFooter()));
-	  },
-	
-	  render: function () {
-	    return dom.div({ className: classnames("debugger theme-body", { "theme-light": !isFirefoxPanel() }) }, SplitBox({
-	      initialWidth: 300,
-	      left: Sources({ sources: this.props.sources }),
-	      right: SplitBox({
-	        initialWidth: 300,
-	        rightFlex: true,
-	        left: this.renderCenterPane(this.props),
-	        right: RightSidebar({ keyShortcuts: this.shortcuts })
-	      })
-	    }));
-	  }
-	});
-	
-	module.exports = connect(state => ({ sources: getSources(state),
-	  selectedSource: getSelectedSource(state) }), dispatch => bindActionCreators(actions, dispatch))(App);
-
-/***/ },
-/* 213 */
-/***/ function(module, exports) {
-
-	/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-	/* vim: set ts=2 et sw=2 tw=80: */
-	/* This Source Code Form is subject to the terms of the Mozilla Public
-	 * License, v. 2.0. If a copy of the MPL was not distributed with this
-	 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-	
-	"use strict";
-	
-	/* globals localStorage, window, document, NodeFilter */
-	
-	// Some constants from nsIPrefBranch.idl.
-	const PREF_INVALID = 0;
-	const PREF_STRING = 32;
-	const PREF_INT = 64;
-	const PREF_BOOL = 128;
-	const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed";
-	
-	/**
-	 * Create a new preference object.
-	 *
-	 * @param {PrefBranch} branch the branch holding this preference
-	 * @param {String} name the base name of this preference
-	 * @param {String} fullName the fully-qualified name of this preference
-	 */
-	function Preference(branch, name, fullName) {
-	  this.branch = branch;
-	  this.name = name;
-	  this.fullName = fullName;
-	  this.defaultValue = null;
-	  this.hasUserValue = false;
-	  this.userValue = null;
-	  this.type = null;
-	}
-	
-	Preference.prototype = {
-	  /**
-	   * Return this preference's current value.
-	   *
-	   * @return {Any} The current value of this preference.  This may
-	   *         return a string, a number, or a boolean depending on the
-	   *         preference's type.
-	   */
-	  get: function () {
-	    if (this.hasUserValue) {
-	      return this.userValue;
-	    }
-	    return this.defaultValue;
-	  },
-	
-	  /**
-	   * Set the preference's value.  The new value is assumed to be a
-	   * user value.  After setting the value, this function emits a
-	   * change notification.
-	   *
-	   * @param {Any} value the new value
-	   */
-	  set: function (value) {
-	    if (!this.hasUserValue || value !== this.userValue) {
-	      this.userValue = value;
-	      this.hasUserValue = true;
-	      this.saveAndNotify();
-	    }
-	  },
-	
-	  /**
-	   * Set the default value for this preference, and emit a
-	   * notification if this results in a visible change.
-	   *
-	   * @param {Any} value the new default value
-	   */
-	  setDefault: function (value) {
-	    if (this.defaultValue !== value) {
-	      this.defaultValue = value;
-	      if (!this.hasUserValue) {
-	        this.saveAndNotify();
-	      }
-	    }
-	  },
-	
-	  /**
-	   * If this preference has a user value, clear it.  If a change was
-	   * made, emit a change notification.
-	   */
-	  clearUserValue: function () {
-	    if (this.hasUserValue) {
-	      this.userValue = null;
-	      this.hasUserValue = false;
-	      this.saveAndNotify();
-	    }
-	  },
-	
-	  /**
-	   * Helper function to write the preference's value to local storage
-	   * and then emit a change notification.
-	   */
-	  saveAndNotify: function () {
-	    let store = {
-	      type: this.type,
-	      defaultValue: this.defaultValue,
-	      hasUserValue: this.hasUserValue,
-	      userValue: this.userValue,
-	    };
-	
-	    localStorage.setItem(this.fullName, JSON.stringify(store));
-	    this.branch._notify(this.name);
-	  },
-	
-	  /**
-	   * Change this preference's value without writing it back to local
-	   * storage.  This is used to handle changes to local storage that
-	   * were made externally.
-	   *
-	   * @param {Number} type one of the PREF_* values
-	   * @param {Any} userValue the user value to use if the pref does not exist
-	   * @param {Any} defaultValue the default value to use if the pref
-	   *        does not exist
-	   * @param {Boolean} hasUserValue if a new pref is created, whether
-	   *        the default value is also a user value
-	   * @param {Object} store the new value of the preference.  It should
-	   *        be of the form {type, defaultValue, hasUserValue, userValue};
-	   *        where |type| is one of the PREF_* type constants; |defaultValue|
-	   *        and |userValue| are the default and user values, respectively;
-	   *        and |hasUserValue| is a boolean indicating whether the user value
-	   *        is valid
-	   */
-	  storageUpdated: function (type, userValue, hasUserValue, defaultValue) {
-	    this.type = type;
-	    this.defaultValue = defaultValue;
-	    this.hasUserValue = hasUserValue;
-	    this.userValue = userValue;
-	    // There's no need to write this back to local storage, since it
-	    // came from there; and this avoids infinite event loops.
-	    this.branch._notify(this.name);
-	  },
-	};
-	
-	/**
-	 * Create a new preference branch.  This object conforms largely to
-	 * nsIPrefBranch and nsIPrefService, though it only implements the
-	 * subset needed by devtools.
-	 *
-	 * @param {PrefBranch} parent the parent branch, or null for the root
-	 *        branch.
-	 * @param {String} name the base name of this branch
-	 * @param {String} fullName the fully-qualified name of this branch
-	 */
-	function PrefBranch(parent, name, fullName) {
-	  this._parent = parent;
-	  this._name = name;
-	  this._fullName = fullName;
-	  this._observers = {};
-	  this._children = {};
-	
-	  if (!parent) {
-	    this._initializeRoot();
-	  }
-	}
-	
-	PrefBranch.prototype = {
-	  PREF_INVALID: PREF_INVALID,
-	  PREF_STRING: PREF_STRING,
-	  PREF_INT: PREF_INT,
-	  PREF_BOOL: PREF_BOOL,
-	
-	  /** @see nsIPrefBranch.root.  */
-	  get root() {
-	    return this._fullName;
-	  },
-	
-	  /** @see nsIPrefBranch.getPrefType.  */
-	  getPrefType: function (prefName) {
-	    return this._findPref(prefName).type;
-	  },
-	
-	  /** @see nsIPrefBranch.getBoolPref.  */
-	  getBoolPref: function (prefName) {
-	    let thePref = this._findPref(prefName);
-	    if (thePref.type !== PREF_BOOL) {
-	      throw new Error(`${prefName} does not have bool type`);
-	    }
-	    return thePref.get();
-	  },
-	
-	  /** @see nsIPrefBranch.setBoolPref.  */
-	  setBoolPref: function (prefName, value) {
-	    if (typeof value !== "boolean") {
-	      throw new Error("non-bool passed to setBoolPref");
-	    }
-	    let thePref = this._findOrCreatePref(prefName, value, true, value);
-	    if (thePref.type !== PREF_BOOL) {
-	      throw new Error(`${prefName} does not have bool type`);
-	    }
-	    thePref.set(value);
-	  },
-	
-	  /** @see nsIPrefBranch.getCharPref.  */
-	  getCharPref: function (prefName) {
-	    let thePref = this._findPref(prefName);
-	    if (thePref.type !== PREF_STRING) {
-	      throw new Error(`${prefName} does not have string type`);
-	    }
-	    return thePref.get();
-	  },
-	
-	  /** @see nsIPrefBranch.setCharPref.  */
-	  setCharPref: function (prefName, value) {
-	    if (typeof value !== "string") {
-	      throw new Error("non-string passed to setCharPref");
-	    }
-	    let thePref = this._findOrCreatePref(prefName, value, true, value);
-	    if (thePref.type !== PREF_STRING) {
-	      throw new Error(`${prefName} does not have string type`);
-	    }
-	    thePref.set(value);
-	  },
-	
-	  /** @see nsIPrefBranch.getIntPref.  */
-	  getIntPref: function (prefName) {
-	    let thePref = this._findPref(prefName);
-	    if (thePref.type !== PREF_INT) {
-	      throw new Error(`${prefName} does not have int type`);
-	    }
-	    return thePref.get();
-	  },
-	
-	  /** @see nsIPrefBranch.setIntPref.  */
-	  setIntPref: function (prefName, value) {
-	    if (typeof value !== "number") {
-	      throw new Error("non-number passed to setIntPref");
-	    }
-	    let thePref = this._findOrCreatePref(prefName, value, true, value);
-	    if (thePref.type !== PREF_INT) {
-	      throw new Error(`${prefName} does not have int type`);
-	    }
-	    thePref.set(value);
-	  },
-	
-	  /** @see nsIPrefBranch.clearUserPref */
-	  clearUserPref: function (prefName) {
-	    let thePref = this._findPref(prefName);
-	    thePref.clearUserValue();
-	  },
-	
-	  /** @see nsIPrefBranch.prefHasUserValue */
-	  prefHasUserValue: function (prefName) {
-	    let thePref = this._findPref(prefName);
-	    return thePref.hasUserValue;
-	  },
-	
-	  /** @see nsIPrefBranch.addObserver */
-	  addObserver: function (domain, observer, holdWeak) {
-	    if (domain !== "" && !domain.endsWith(".")) {
-	      throw new Error("invalid domain to addObserver: " + domain);
-	    }
-	    if (holdWeak) {
-	      throw new Error("shim prefs only supports strong observers");
-	    }
-	
-	    if (!(domain in this._observers)) {
-	      this._observers[domain] = [];
-	    }
-	    this._observers[domain].push(observer);
-	  },
-	
-	  /** @see nsIPrefBranch.removeObserver */
-	  removeObserver: function (domain, observer) {
-	    if (!(domain in this._observers)) {
-	      return;
-	    }
-	    let index = this._observers[domain].indexOf(observer);
-	    if (index >= 0) {
-	      this._observers[domain].splice(index, 1);
-	    }
-	  },
-	
-	  /** @see nsIPrefService.savePrefFile */
-	  savePrefFile: function (file) {
-	    if (file) {
-	      throw new Error("shim prefs only supports null file in savePrefFile");
-	    }
-	    // Nothing to do - this implementation always writes back.
-	  },
-	
-	  /** @see nsIPrefService.getBranch */
-	  getBranch: function (prefRoot) {
-	    if (!prefRoot) {
-	      return this;
-	    }
-	    if (prefRoot.endsWith(".")) {
-	      prefRoot = prefRoot.slice(0, -1);
-	    }
-	    // This is a bit weird since it could erroneously return a pref,
-	    // not a pref branch.
-	    return this._findPref(prefRoot);
-	  },
-	
-	  /**
-	   * Helper function to find either a Preference or PrefBranch object
-	   * given its name.  If the name is not found, throws an exception.
-	   *
-	   * @param {String} prefName the fully-qualified preference name
-	   * @return {Object} Either a Preference or PrefBranch object
-	   */
-	  _findPref: function (prefName) {
-	    let branchNames = prefName.split(".");
-	    let branch = this;
-	
-	    for (let branchName of branchNames) {
-	      branch = branch._children[branchName];
-	      if (!branch) {
-	        throw new Error("could not find pref branch " + prefName);
-	      }
-	    }
-	
-	    return branch;
-	  },
-	
-	  /**
-	   * Helper function to notify any observers when a preference has
-	   * changed.  This will also notify the parent branch for further
-	   * reporting.
-	   *
-	   * @param {String} relativeName the name of the updated pref,
-	   *        relative to this branch
-	   */
-	  _notify: function (relativeName) {
-	    for (let domain in this._observers) {
-	      if (relativeName.startsWith(domain)) {
-	        // Allow mutation while walking.
-	        let localList = this._observers[domain].slice();
-	        for (let observer of localList) {
-	          try {
-	            observer.observe(this, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID,
-	                             relativeName);
-	          } catch (e) {
-	            console.error(e);
-	          }
-	        }
-	      }
-	    }
-	
-	    if (this._parent) {
-	      this._parent._notify(this._name + "." + relativeName);
-	    }
-	  },
-	
-	  /**
-	   * Helper function to create a branch given an array of branch names
-	   * representing the path of the new branch.
-	   *
-	   * @param {Array} branchList an array of strings, one per component
-	   *        of the branch to be created
-	   * @return {PrefBranch} the new branch
-	   */
-	  _createBranch: function (branchList) {
-	    let parent = this;
-	    for (let branch of branchList) {
-	      if (!parent._children[branch]) {
-	        parent._children[branch] = new PrefBranch(parent, branch,
-	                                                  parent.root + "." + branch);
-	      }
-	      parent = parent._children[branch];
-	    }
-	    return parent;
-	  },
-	
-	  /**
-	   * Create a new preference.  The new preference is assumed to be in
-	   * local storage already, and the new value is taken from there.
-	   *
-	   * @param {String} keyName the full-qualified name of the preference.
-	   *        This is also the name of the key in local storage.
-	   * @param {Any} userValue the user value to use if the pref does not exist
-	   * @param {Any} defaultValue the default value to use if the pref
-	   *        does not exist
-	   * @param {Boolean} hasUserValue if a new pref is created, whether
-	   *        the default value is also a user value
-	   */
-	  _findOrCreatePref: function (keyName, userValue, hasUserValue, defaultValue) {
-	    let branchName = keyName.split(".");
-	    let prefName = branchName.pop();
-	
-	    let branch = this._createBranch(branchName);
-	    if (!(prefName in branch._children)) {
-	      if (hasUserValue && typeof (userValue) !== typeof (defaultValue)) {
-	        throw new Error("inconsistent values when creating " + keyName);
-	      }
-	
-	      let type;
-	      switch (typeof (defaultValue)) {
-	        case "boolean":
-	          type = PREF_BOOL;
-	          break;
-	        case "number":
-	          type = PREF_INT;
-	          break;
-	        case "string":
-	          type = PREF_STRING;
-	          break;
-	        default:
-	          throw new Error("unhandled argument type: " + typeof (defaultValue));
-	      }
-	
-	      let thePref = new Preference(branch, prefName, keyName);
-	      thePref.storageUpdated(type, userValue, hasUserValue, defaultValue);
-	      branch._children[prefName] = thePref;
-	    }
-	
-	    return branch._children[prefName];
-	  },
-	
-	  /**
-	   * Helper function that is called when local storage changes.  This
-	   * updates the preferences and notifies pref observers as needed.
-	   *
-	   * @param {StorageEvent} event the event representing the local
-	   *        storage change
-	   */
-	  _onStorageChange: function (event) {
-	    if (event.storageArea !== localStorage) {
-	      return;
-	    }
-	
-	    // Ignore delete events.  Not clear what's correct.
-	    if (event.key === null || event.newValue === null) {
-	      return;
-	    }
-	
-	    let {type, userValue, hasUserValue, defaultValue} =
-	        JSON.parse(event.newValue);
-	    if (event.oldValue === null) {
-	      this._findOrCreatePref(event.key, userValue, hasUserValue, defaultValue);
-	    } else {
-	      let thePref = this._findPref(event.key);
-	      thePref.storageUpdated(type, userValue, hasUserValue, defaultValue);
-	    }
-	  },
-	
-	  /**
-	   * Helper function to initialize the root PrefBranch.
-	   */
-	  _initializeRoot: function () {
-	    try {
-	      if (localStorage.length === 0) {
-	        // FIXME - this is where we'll load devtools.js to install the
-	        // default prefs.
-	      }
-	    } catch(e) {
-	      // Couldn't access localStorage; bail. This happens in the
-	      // Firefox panel because Chrome-privileged code can't access it.
-	      return;
-	    }
-	
-	    // Read the prefs from local storage and create the local
-	    // representations.
-	    for (let i = 0; i < localStorage.length; ++i) {
-	      let keyName = localStorage.key(i);
-	      try {
-	        let {userValue, hasUserValue, defaultValue} =
-	            JSON.parse(localStorage.getItem(keyName));
-	
-	        this._findOrCreatePref(keyName, userValue, hasUserValue, defaultValue);
-	      } catch (e) {
-	      }
-	    }
-	
-	    this._onStorageChange = this._onStorageChange.bind(this);
-	    window.addEventListener("storage", this._onStorageChange);
-	  },
-	};
-	
-	const Services = {
-	  /**
-	   * An implementation of nsIPrefService that is based on local
-	   * storage.  Only the subset of nsIPrefService that is actually used
-	   * by devtools is implemented here.
-	   */
-	  prefs: new PrefBranch(null, "", ""),
-	
-	  /**
-	   * An implementation of Services.appinfo that holds just the
-	   * properties needed by devtools.
-	   */
-	  appinfo: {
-	    get OS() {
-	      const os = window.navigator.userAgent;
-	      if (os) {
-	        if (os.includes("Linux")) {
-	          return "Linux";
-	        } else if (os.includes("Windows")) {
-	          return "WINNT";
-	        } else if (os.includes("Mac")) {
-	          return "Darwin";
-	        }
-	      }
-	      return "Unknown";
-	    },
-	
-	    // It's fine for this to be an approximation.
-	    get name() {
-	      return window.navigator.userAgent;
-	    },
-	
-	    // It's fine for this to be an approximation.
-	    get version() {
-	      return window.navigator.appVersion;
-	    },
-	
-	    // This is only used by telemetry, which is disabled for the
-	    // content case.  So, being totally wrong is ok.
-	    get is64Bit() {
-	      return true;
-	    },
-	  },
-	
-	  /**
-	   * A no-op implementation of Services.telemetry.  This supports just
-	   * the subset of Services.telemetry that is used by devtools.
-	   */
-	  telemetry: {
-	    getHistogramById: function (name) {
-	      return {
-	        add: () => {}
-	      };
-	    },
-	
-	    getKeyedHistogramById: function (name) {
-	      return {
-	        add: () => {}
-	      };
-	    },
-	  },
-	
-	  /**
-	   * An implementation of Services.focus that holds just the
-	   * properties and methods needed by devtools.
-	   * @see nsIFocusManager.idl for details.
-	   */
-	  focus: {
-	    // These values match nsIFocusManager in order to make testing a
-	    // bit simpler.
-	    MOVEFOCUS_FORWARD: 1,
-	    MOVEFOCUS_BACKWARD: 2,
-	
-	    get focusedElement() {
-	      if (!document.hasFocus()) {
-	        return null;
-	      }
-	      return document.activeElement;
-	    },
-	
-	    moveFocus: function (window, startElement, type, flags) {
-	      if (flags !== 0) {
-	        throw new Error("shim Services.focus.moveFocus only accepts flags===0");
-	      }
-	      if (type !== Services.focus.MOVEFOCUS_FORWARD
-	          && type !== Services.focus.MOVEFOCUS_BACKWARD) {
-	        throw new Error("shim Services.focus.moveFocus only supports " +
-	                        " MOVEFOCUS_FORWARD and MOVEFOCUS_BACKWARD");
-	      }
-	
-	      if (!startElement) {
-	        startElement = document.activeElement || document;
-	      }
-	
-	      let iter = document.createTreeWalker(document, NodeFilter.SHOW_ELEMENT, {
-	        acceptNode: function (node) {
-	          let tabIndex = node.getAttribute("tabindex");
-	          if (tabIndex === "-1") {
-	            return NodeFilter.FILTER_SKIP;
-	          }
-	          node.focus();
-	          if (document.activeElement == node) {
-	            return NodeFilter.FILTER_ACCEPT;
-	          }
-	          return NodeFilter.FILTER_SKIP;
-	        }
-	      });
-	
-	      iter.currentNode = startElement;
-	
-	      // Sets the focus via side effect in the filter.
-	      if (type === Services.focus.MOVEFOCUS_FORWARD) {
-	        iter.nextNode();
-	      } else {
-	        iter.previousNode();
-	      }
-	    },
-	  },
-	};
-	
-	/**
-	 * Create a new preference.  This is used during startup (see
-	 * devtools/client/preferences/devtools.js) to install the
-	 * default preferences.
-	 *
-	 * @param {String} name the name of the preference
-	 * @param {Any} value the default value of the preference
-	 */
-	function pref(name, value) {
-	  let thePref = Services.prefs._findOrCreatePref(name, value, true, value);
-	  thePref.setDefault(value);
-	}
-	
-	exports.Services = Services;
-	// This is exported to silence eslint and, at some point, perhaps to
-	// provide it when loading devtools.js in order to install the default
-	// preferences.
-	exports.pref = pref;
-
-
-/***/ },
-/* 214 */
-/***/ function(module, exports, __webpack_require__) {
-
-	
-	
-	var breakpoints = __webpack_require__(215);
-	var eventListeners = __webpack_require__(218);
-	var sources = __webpack_require__(219);
-	var tabs = __webpack_require__(222);
-	var pause = __webpack_require__(223);
-	var navigation = __webpack_require__(224);
-	
-	module.exports = Object.assign(navigation, breakpoints, eventListeners, sources, tabs, pause);
-
-/***/ },
-/* 215 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
-	
-	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) { return step("next", value); }, function (err) { return 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/. */
-	
-	/**
-	 * Redux actions for breakpoints
-	 * @module actions/breakpoints
-	 */
-	
-	var constants = __webpack_require__(190);
-	
-	var _require = __webpack_require__(184);
-	
-	var PROMISE = _require.PROMISE;
-	
-	var _require2 = __webpack_require__(199);
-	
-	var getBreakpoint = _require2.getBreakpoint;
-	var getBreakpoints = _require2.getBreakpoints;
-	
-	var _require3 = __webpack_require__(216);
-	
-	var getOriginalLocation = _require3.getOriginalLocation;
-	var getGeneratedLocation = _require3.getGeneratedLocation;
-	
-	/**
-	 * Argument parameters via Thunk middleware for {@link https://github.com/gaearon/redux-thunk|Redux Thunk}
-	 *
-	 * @memberof actions/breakpoints
-	 * @static
-	 * @typedef {Object} ThunkArgs
-	 */
-	
-	function _breakpointExists(state, location) {
-	  var currentBp = getBreakpoint(state, location);
-	  return currentBp && !currentBp.disabled;
-	}
-	
-	function _getOrCreateBreakpoint(state, location, condition) {
-	  return getBreakpoint(state, location) || { location, condition };
-	}
-	
-	/**
-	 * Enabling a breakpoint calls {@link addBreakpoint}
-	 * which will reuse the existing breakpoint information that is stored.
-	 *
-	 * @memberof actions/breakpoints
-	 * @static
-	 */
-	function enableBreakpoint(location) {
-	  return addBreakpoint(location);
-	}
-	
-	/**
-	 * Add a new or enable an existing breakpoint
-	 *
-	 * @memberof actions/breakpoints
-	 * @static
-	 * @param {String} $1.condition Conditional breakpoint condition value
-	 * @param {Function} $1.getTextForLine Get the text to represent the line
-	 */
-	function addBreakpoint(location) {
-	  var _ref = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
-	
-	  var condition = _ref.condition;
-	  var getTextForLine = _ref.getTextForLine;
-	
-	  return _ref2 => {
-	    var dispatch = _ref2.dispatch;
-	    var getState = _ref2.getState;
-	    var client = _ref2.client;
-	
-	    if (_breakpointExists(getState(), location)) {
-	      return Promise.resolve();
-	    }
-	
-	    var bp = _getOrCreateBreakpoint(getState(), location, condition);
-	
-	    return dispatch({
-	      type: constants.ADD_BREAKPOINT,
-	      breakpoint: bp,
-	      condition: condition,
-	      [PROMISE]: _asyncToGenerator(function* () {
-	        location = yield getGeneratedLocation(getState(), bp.location);
-	
-	        var _ref4 = yield client.setBreakpoint(location, bp.condition);
-	
-	        var id = _ref4.id;
-	        var actualLocation = _ref4.actualLocation;
-	
-	
-	        actualLocation = yield getOriginalLocation(getState(), actualLocation);
-	
-	        // If this breakpoint is being re-enabled, it already has a
-	        // text snippet.
-	        var text = bp.text;
-	        if (!text) {
-	          text = getTextForLine ? getTextForLine(actualLocation.line) : "";
-	        }
-	
-	        return { id, actualLocation, text };
-	      })()
-	    });
-	  };
-	}
-	
-	/**
-	 * Disable a single breakpoint
-	 *
-	 * @memberof actions/breakpoints
-	 * @static
-	 */
-	function disableBreakpoint(location) {
-	  return _removeOrDisableBreakpoint(location, true);
-	}
-	
-	/**
-	 * Remove a single breakpoint
-	 *
-	 * @memberof actions/breakpoints
-	 * @static
-	 */
-	function removeBreakpoint(location) {
-	  return _removeOrDisableBreakpoint(location);
-	}
-	
-	function _removeOrDisableBreakpoint(location, isDisabled) {
-	  return _ref5 => {
-	    var dispatch = _ref5.dispatch;
-	    var getState = _ref5.getState;
-	    var client = _ref5.client;
-	
-	    var bp = 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");
-	    }
-	
-	    var action = {
-	      type: constants.REMOVE_BREAKPOINT,
-	      breakpoint: bp,
-	      disabled: isDisabled
-	    };
-	
-	    // If the breakpoint is already disabled, we don't need to remove
-	    // it from the server. We just need to dispatch an action
-	    // simulating a successful server request to remove it, and it
-	    // will be removed completely from the state.
-	    if (!bp.disabled) {
-	      return dispatch(Object.assign({}, action, {
-	        [PROMISE]: client.removeBreakpoint(bp.id)
-	      }));
-	    }
-	    return dispatch(Object.assign({}, action, { status: "done" }));
-	  };
-	}
-	
-	/**
-	 * Toggle All Breakpoints
-	 *
-	 * @memberof actions/breakpoints
-	 * @static
-	 */
-	function toggleAllBreakpoints(shouldDisableBreakpoints) {
-	  return _ref6 => {
-	    var dispatch = _ref6.dispatch;
-	    var getState = _ref6.getState;
-	
-	    var breakpoints = getBreakpoints(getState());
-	    return dispatch({
-	      type: constants.TOGGLE_BREAKPOINTS,
-	      shouldDisableBreakpoints,
-	      [PROMISE]: _asyncToGenerator(function* () {
-	        for (var _ref8 of breakpoints) {
-	          var _ref9 = _slicedToArray(_ref8, 2);
-	
-	          var breakpoint = _ref9[1];
-	
-	          if (shouldDisableBreakpoints) {
-	            yield dispatch(disableBreakpoint(breakpoint.location));
-	          } else {
-	            yield dispatch(enableBreakpoint(breakpoint.location));
-	          }
-	        }
-	      })()
-	    });
-	  };
-	}
-	
-	/**
-	 * Update the condition of a breakpoint.
-	 *  **NOT IMPLEMENTED**
-	 *
-	 * @throws {Error} "not implemented"
-	 * @memberof actions/breakpoints
-	 * @static
-	 * @param {Location} location
-	 *        @see DebuggerController.Breakpoints.addBreakpoint
-	 * @param {string} condition
-	 *        The condition to set on the breakpoint
-	 */
-	function setBreakpointCondition(location, condition) {
-	  throw new Error("not implemented");
-	
-	  // return ({ dispatch, getState, client }) => {
-	  //   const bp = getBreakpoint(getState(), location);
-	  //   if (!bp) {
-	  //     throw new Error("Breakpoint does not exist at the specified location");
-	  //   }
-	  //   if (bp.get("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 dispatch({
-	  //     type: constants.SET_BREAKPOINT_CONDITION,
-	  //     breakpoint: bp,
-	  //     condition: condition,
-	  //     [PROMISE]: Task.spawn(function* () {
-	  //       yield client.setBreakpointCondition(bp.get("id"), condition);
-	  //     })
-	  //   });
-	  // };
+/* 233 */
+/***/ function(module, exports) {
+
+	
+	
+	/**
+	 * Trims the query part or reference identifier of a url string, if necessary.
+	 */
+	function trimUrlQuery(url) {
+	  var length = url.length;
+	  var q1 = url.indexOf("?");
+	  var q2 = url.indexOf("&");
+	  var q3 = url.indexOf("#");
+	  var q = Math.min(q1 != -1 ? q1 : length, q2 != -1 ? q2 : length, q3 != -1 ? q3 : length);
+	
+	  return url.slice(0, q);
+	}
+	
+	/**
+	 * Returns true if the specified url and/or content type are specific to
+	 * javascript files.
+	 *
+	 * @return boolean
+	 *         True if the source is likely javascript.
+	 */
+	function isJavaScript(url) {
+	  var contentType = arguments.length <= 1 || arguments[1] === undefined ? "" : arguments[1];
+	
+	  return url && /\.(jsm|js)?$/.test(trimUrlQuery(url)) || contentType.includes("javascript");
+	}
+	
+	// TODO: This should use a shared Source type
+	function isPretty(source) {
+	  return source.url ? /formatted$/.test(source.url) : false;
 	}
 	
 	module.exports = {
-	  enableBreakpoint,
-	  addBreakpoint,
-	  disableBreakpoint,
-	  removeBreakpoint,
-	  toggleAllBreakpoints,
-	  setBreakpointCondition
-	};
-
-/***/ },
-/* 216 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var getOriginalSources = (() => {
-	  var _ref = _asyncToGenerator(function* (state, source) {
-	    var originalSourceUrls = yield getOriginalSourceUrls(source);
-	    return originalSourceUrls.map(function (url) {
-	      return getSourceByURL(state, url);
-	    });
-	  });
-	
-	  return function getOriginalSources(_x, _x2) {
-	    return _ref.apply(this, arguments);
-	  };
-	})();
-	
-	var getGeneratedLocation = (() => {
-	  var _ref2 = _asyncToGenerator(function* (state, location) {
-	    var source = getSource(state, location.sourceId);
-	
-	    if (!source) {
-	      return location;
-	    }
-	
-	    if (yield isOriginal(source.toJS())) {
-	      return yield getGeneratedSourceLocation(source.toJS(), location);
-	    }
-	
-	    return location;
-	  });
-	
-	  return function getGeneratedLocation(_x3, _x4) {
-	    return _ref2.apply(this, arguments);
-	  };
-	})();
-	
-	var getOriginalLocation = (() => {
-	  var _ref3 = _asyncToGenerator(function* (state, location) {
-	    var source = getSource(state, location.sourceId);
-	
-	    if (!source) {
-	      return location;
-	    }
-	
-	    if (isGenerated(source.toJS())) {
-	      var originalPosition = yield getOriginalSourcePosition(source.toJS(), location);
-	
-	      var url = originalPosition.url;
-	      var line = originalPosition.line;
-	
-	      if (!url) {
-	        return {
-	          sourceId: source.get("id"),
-	          line: location.line
-	        };
-	      }
-	
-	      var originalSource = getSourceByURL(state, url);
-	
-	      return {
-	        sourceId: originalSource.get("id"),
-	        line
-	      };
-	    }
-	
-	    return location;
-	  });
-	
-	  return function getOriginalLocation(_x5, _x6) {
-	    return _ref3.apply(this, arguments);
-	  };
-	})();
-	
-	var getOriginalSourceTexts = (() => {
-	  var _ref4 = _asyncToGenerator(function* (state, generatedSource, generatedText) {
-	    if (!_shouldSourceMap(generatedSource)) {
-	      return [];
-	    }
-	
-	    var originalTexts = yield getOriginalTexts(generatedSource, generatedText);
-	
-	    return originalTexts.map(function (_ref5) {
-	      var text = _ref5.text;
-	      var url = _ref5.url;
-	
-	      var id = getSourceByURL(state, url).get("id");
-	      var contentType = "text/javascript";
-	      return { text, id, contentType };
-	    });
-	  });
-	
-	  return function getOriginalSourceTexts(_x7, _x8, _x9) {
-	    return _ref4.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) { return step("next", value); }, function (err) { return step("throw", err); }); } } return step("next"); }); }; }
-	
-	var _require = __webpack_require__(176);
-	
-	var workerTask = _require.workerTask;
-	
-	var _require2 = __webpack_require__(217);
-	
-	var makeOriginalSource = _require2.makeOriginalSource;
-	var getGeneratedSourceId = _require2.getGeneratedSourceId;
-	
-	var _require3 = __webpack_require__(199);
-	
-	var getSource = _require3.getSource;
-	var getSourceByURL = _require3.getSourceByURL;
-	
-	var _require4 = __webpack_require__(46);
-	
-	var isEnabled = _require4.isEnabled;
-	var getValue = _require4.getValue;
-	
-	
-	var sourceMapWorker = void 0;
-	function restartWorker() {
-	  if (sourceMapWorker) {
-	    sourceMapWorker.terminate();
-	  }
-	  sourceMapWorker = new Worker(getValue("baseWorkerURL") + "source-map-worker.js");
-	}
-	restartWorker();
-	
-	function destroy() {
-	  if (sourceMapWorker) {
-	    sourceMapWorker.terminate();
-	    sourceMapWorker = null;
-	  }
-	}
-	
-	var sourceMapTask = function (method) {
-	  return function () {
-	    var args = Array.prototype.slice.call(arguments);
-	    return workerTask(sourceMapWorker, { method, args });
-	  };
-	};
-	
-	var getOriginalSourcePosition = sourceMapTask("getOriginalSourcePosition");
-	var getGeneratedSourceLocation = sourceMapTask("getGeneratedSourceLocation");
-	var createOriginalSources = sourceMapTask("createOriginalSources");
-	var getOriginalSourceUrls = sourceMapTask("getOriginalSourceUrls");
-	var getOriginalTexts = sourceMapTask("getOriginalTexts");
-	var createSourceMap = sourceMapTask("createSourceMap");
-	var clearData = sourceMapTask("clearData");
-	
-	function _shouldSourceMap(source) {
-	  return isEnabled("sourceMaps") && source.sourceMapURL;
-	}
-	
-	function isMapped(source) {
-	  return _shouldSourceMap(source);
-	}
-	
-	function isOriginal(originalSource) {
-	  return !!getGeneratedSourceId(originalSource);
-	}
-	
-	function isGenerated(source) {
-	  return !isOriginal(source);
-	}
-	
-	function getGeneratedSource(state, source) {
-	  if (isGenerated(source)) {
-	    return source;
-	  }
-	
-	  var generatedSourceId = getGeneratedSourceId(source);
-	  var originalSource = getSource(state, generatedSourceId);
-	
-	  if (originalSource) {
-	    return originalSource.toJS();
-	  }
-	
-	  return source;
-	}
-	
-	module.exports = {
-	  getGeneratedLocation,
-	  getOriginalLocation,
-	  makeOriginalSource,
-	  getOriginalSources,
-	  getGeneratedSource,
-	  getOriginalSourceTexts,
-	  getOriginalSourcePosition,
-	  getGeneratedSourceLocation,
-	  createOriginalSources,
-	  getOriginalSourceUrls,
-	  isOriginal,
-	  isGenerated,
-	  isMapped,
-	  getGeneratedSourceId,
-	  createSourceMap,
-	  clearData,
-	  restartWorker,
-	  destroy
-	};
-
-/***/ },
-/* 217 */
-/***/ function(module, exports) {
-
-	
-	function getGeneratedSourceId(originalSource) {
-	  var match = originalSource.id.match(/(.*)\/originalSource/);
-	  return match ? match[1] : null;
-	}
-	
-	function makeOriginalSource(_ref) {
-	  var url = _ref.url;
-	  var source = _ref.source;
-	  var _ref$id = _ref.id;
-	  var id = _ref$id === undefined ? 1 : _ref$id;
-	
-	  var generatedSourceId = source.id;
-	  return {
-	    url,
-	    id: `${ generatedSourceId }/originalSource${ id }`,
-	    isPrettyPrinted: false
-	  };
-	}
-	
-	module.exports = {
-	  makeOriginalSource,
-	  getGeneratedSourceId
-	};
-
-/***/ },
-/* 218 */
+	  isJavaScript,
+	  isPretty
+	};
+
+/***/ },
+/* 234 */
 /***/ 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/. */
 	/* global window gThreadClient setNamedTimeout services EVENTS */
 	/* eslint no-shadow: 0  */
 	
 	/**
 	 * Redux actions for the event listeners state
 	 * @module actions/event-listeners
 	 */
 	
 	var constants = __webpack_require__(190);