text: (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  var recorder = require('./lib/recorder');
  module.exports = require('./lib/scope');
  
  module.exports.recorder = {
      rec  : recorder.record
    , clear   : recorder.clear
    , play : recorder.outputs
  };
  
  module.exports.back = require('./lib/back');
  module.exports.restore = recorder.restore;
  
  },{"./lib/back":2,"./lib/recorder":8,"./lib/scope":10}],2:[function(require,module,exports){
  (function (process){
  'use strict';
  
  var nock = require('./scope');
  var recorder = require('./recorder');
  
  var format = require('util').format;
  var mkdirp = require('mkdirp');
  var path = require('path');
  var expect = require('chai').expect;
  var debug = require('debug')('nock.back');
  
  var _mode = null;
  
  var fs;
  
  try {
    fs = require('fs');
  } catch(err) {
    // do nothing, probably in browser
  }
  
  
  
  /**
   * nock the current function with the fixture given
   *
   * @param {string}   fixtureName  - the name of the fixture, e.x. 'foo.json'
   * @param {object}   options      - [optional], extra options for nock with, e.x. { assert: true }
   * @param {function} nockedFn     - the callback function to be executed with the given fixture being loaded,
   *                                  the function will be called with { scopes: loaded_nocks || [] } set as this
   *
   *
   * List of options:
   *
   * @param {function} before       - a preprocessing function, gets called before nock.define
   * @param {function} after        - a postprocessing function, gets called after nock.define
   * @param {function} afterRecord  - a postprocessing function, gets called after recording. Is passed the array
   *                                  of scopes recorded and should return the array scopes to save to the fixture
  
   *
   */
  function Back (fixtureName, options, nockedFn) {
    if(!Back.fixtures) {
      throw new Error(  'Back requires nock.back.fixtures to be set\n' +
                        'Ex:\n' +
                        '\trequire(nock).back.fixtures = \'/path/to/fixures/\'');
    }
  
    if( arguments.length === 2 ) {
      nockedFn = options;
      options = {};
    }
  
    _mode.setup();
  
    var fixture = path.join(Back.fixtures, fixtureName)
      , context = _mode.start(fixture, options);
  
  
    var nockDone = function () {
      _mode.finish(fixture, options, context);
    };
  
    debug('context:', context);
  
    nockedFn.call(context, nockDone);
  }
  
  
  
  
  /*******************************************************************************
  *                                    Modes                                     *
  *******************************************************************************/
  
  
  var wild = {
  
  
    setup: function () {
      nock.cleanAll();
      recorder.restore();
      nock.activate();
      nock.enableNetConnect();
    },
  
  
    start: function () {
      return load(); //don't load anything but get correct context
    },
  
  
    finish: function () {
      //nothing to do
    }
  
  
  };
  
  
  
  
  var dryrun = {
  
  
    setup: function () {
      recorder.restore();
      nock.cleanAll();
      nock.activate();
      //  We have to explicitly enable net connectivity as by default it's off.
      nock.enableNetConnect();
    },
  
  
    start: function (fixture, options) {
      var contexts = load(fixture, options);
  
      nock.enableNetConnect();
      return contexts;
    },
  
  
    finish: function () {
      //nothing to do
    }
  
  
  };
  
  
  
  
  var record = {
  
  
    setup: function () {
      recorder.restore();
      recorder.clear();
      nock.cleanAll();
      nock.activate();
      nock.disableNetConnect();
    },
  
  
    start: function (fixture, options) {
      if (! fs) {
        throw new Error('no fs');
      }
      var context = load(fixture, options);
  
      if( !context.isLoaded ) {
        recorder.record({
          dont_print: true,
          output_objects: true
        });
  
        context.isRecording = true;
      }
  
      return context;
    },
  
  
    finish: function (fixture, options, context) {
      if( context.isRecording ) {
        var outputs = recorder.outputs();
  
        if( typeof options.afterRecord === 'function' ) {
          outputs = options.afterRecord(outputs);
        }
  
        outputs = JSON.stringify(outputs, null, 4);
        debug('recorder outputs:', outputs);
  
        mkdirp.sync(path.dirname(fixture));
        fs.writeFileSync(fixture, outputs);
      }
    }
  
  
  };
  
  
  
  
  var lockdown = {
  
  
    setup: function () {
      recorder.restore();
      recorder.clear();
      nock.cleanAll();
      nock.activate();
      nock.disableNetConnect();
    },
  
  
    start: function (fixture, options) {
      return load(fixture, options);
    },
  
  
    finish: function () {
      //nothing to do
    }
  
  
  };
  
  
  
  
  function load (fixture, options) {
    var context = {
      scopes : [],
      assertScopesFinished: function () {
        assertScopes(this.scopes, fixture);
      }
    };
  
    if( fixture && fixtureExists(fixture) ) {
      var scopes = nock.loadDefs(fixture);
      applyHook(scopes, options.before);
  
      scopes = nock.define(scopes);
      applyHook(scopes, options.after);
  
      context.scopes = scopes;
      context.isLoaded = true;
    }
  
  
    return context;
  }
  
  
  
  
  function applyHook(scopes, fn) {
    if( !fn ) {
      return;
    }
  
    if( typeof fn !== 'function' ) {
      throw new Error ('processing hooks must be a function');
    }
  
    scopes.forEach(fn);
  }
  
  
  
  
  function fixtureExists(fixture) {
    if (! fs) {
      throw new Error('no fs');
    }
  
    return fs.existsSync(fixture);
  }
  
  
  
  
  function assertScopes (scopes, fixture) {
    scopes.forEach(function (scope) {
      expect( scope.isDone() )
      .to.be.equal(
        true,
        format('%j was not used, consider removing %s to rerecord fixture', scope.pendingMocks(), fixture)
      );
    });
  }
  
  
  
  
  var Modes = {
  
    wild: wild, //all requests go out to the internet, dont replay anything, doesnt record anything
  
    dryrun: dryrun, //use recorded nocks, allow http calls, doesnt record anything, useful for writing new tests (default)
  
    record: record, //use recorded nocks, record new nocks
  
    lockdown: lockdown, //use recorded nocks, disables all http calls even when not nocked, doesnt record
  
  };
  
  
  
  
  
  Back.setMode = function(mode) {
    if( !Modes.hasOwnProperty(mode) ) {
      throw new Error ('some usage error');
    }
  
    Back.currentMode = mode;
    debug('New nock back mode:', Back.currentMode);
  
    _mode = Modes[mode];
    _mode.setup();
  };
  
  
  
  
  Back.fixtures = null;
  Back.currentMode = null;
  Back.setMode(process.env.NOCK_BACK_MODE || 'dryrun');
  
  module.exports = exports = Back;
  
  }).call(this,require('_process'))
  },{"./recorder":8,"./scope":10,"_process":25,"chai":56,"debug":92,"fs":12,"mkdirp":100,"path":24,"util":54}],3:[function(require,module,exports){
  (function (Buffer){
  'use strict';
  
  var _ = require('lodash');
  var debug = require('debug')('nock.common');
  
  /**
   * Normalizes the request options so that it always has `host` property.
   *
   * @param  {Object} options - a parsed options object of the request
   */
  var normalizeRequestOptions = function(options) {
    options.proto = options.proto || (options._https_ ? 'https': 'http');
    options.port = options.port || ((options.proto === 'http') ? 80 : 443);
    if (options.host) {
      debug('options.host:', options.host);
      if (! options.hostname) {
        if (options.host.split(':').length == 2) {
          options.hostname = options.host.split(':')[0];
        } else {
          options.hostname = options.host;
        }
      }
    }
    debug('options.hostname in the end: %j', options.hostname);
    options.host = (options.hostname || 'localhost') + ':' + options.port;
    debug('options.host in the end: %j', options.host);
  
    /// lowercase host names
    ['hostname', 'host'].forEach(function(attr) {
      if (options[attr]) {
        options[attr] = options[attr].toLowerCase();
      }
    })
  
    return options;
  };
  
  /**
   * Returns true if the data contained in buffer is binary which in this case means
   * that it cannot be reconstructed from its utf8 representation.
   *
   * @param  {Object} buffer - a Buffer object
   */
  var isBinaryBuffer = function(buffer) {
  
    if(!Buffer.isBuffer(buffer)) {
      return false;
    }
  
    //  Test if the buffer can be reconstructed verbatim from its utf8 encoding.
    var utfEncodedBuffer = buffer.toString('utf8');
    var reconstructedBuffer = new Buffer(utfEncodedBuffer, 'utf8');
    var compareBuffers = function(lhs, rhs) {
      if(lhs.length !== rhs.length) {
        return false;
      }
  
      for(var i = 0; i < lhs.length; ++i) {
        if(lhs[i] !== rhs[i]) {
          return false;
        }
      }
  
      return true;
    };
  
    //  If the buffers are *not* equal then this is a "binary buffer"
    //  meaning that it cannot be faitfully represented in utf8.
    return !compareBuffers(buffer, reconstructedBuffer);
  
  };
  
  /**
   * If the chunks are Buffer objects then it returns a single Buffer object with the data from all the chunks.
   * If the chunks are strings then it returns a single string value with data from all the chunks.
   *
   * @param  {Array} chunks - an array of Buffer objects or strings
   */
  var mergeChunks = function(chunks) {
  
    if(_.isEmpty(chunks)) {
      return new Buffer(0);
    }
  
    //  We assume that all chunks are Buffer objects if the first is buffer object.
    var areBuffers = Buffer.isBuffer(_.first(chunks));
  
    if(!areBuffers) {
      //  When the chunks are not buffers we assume that they are strings.
      return chunks.join('');
    }
  
    //  Merge all the buffers into a single Buffer object.
    return Buffer.concat(chunks);
  
  };
  
  //  Array where all information about all the overridden requests are held.
  var requestOverride = [];
  
  /**
   * Overrides the current `request` function of `http` and `https` modules with
   * our own version which intercepts issues HTTP/HTTPS requests and forwards them
   * to the given `newRequest` function.
   *
   * @param  {Function} newRequest - a function handling requests; it accepts four arguments:
   *   - proto - a string with the overridden module's protocol name (either `http` or `https`)
   *   - overriddenRequest - the overridden module's request function already bound to module's object
   *   - options - the options of the issued request
   *   - callback - the callback of the issued request
   */
  var overrideRequests = function(newRequest) {
    debug('overriding requests');
  
    ['http', 'https'].forEach(function(proto) {
      debug('- overriding request for', proto);
  
      var moduleName = proto, // 1 to 1 match of protocol and module is fortunate :)
          module = {
            http: require('http'),
            https: require('https')
          }[moduleName],
          overriddenRequest = module.request;
  
      if(requestOverride[moduleName]) {
        throw new Error('Module\'s request already overridden for ' + moduleName + ' protocol.');
      }
  
      //  Store the properties of the overridden request so that it can be restored later on.
      requestOverride[moduleName] = {
        module: module,
        request: overriddenRequest
      };
  
      module.request = function(options, callback) {
        // debug('request options:', options);
        return newRequest(proto, overriddenRequest.bind(module), options, callback);
      };
  
      debug('- overridden request for', proto);
    });
  };
  
  /**
   * Restores `request` function of `http` and `https` modules to values they
   * held before they were overridden by us.
   */
  var restoreOverriddenRequests = function() {
    debug('restoring requests');
  
    //  Restore any overridden requests.
    _(requestOverride).keys().each(function(proto) {
      debug('- restoring request for', proto);
  
      var override = requestOverride[proto];
      if(override) {
        override.module.request = override.request;
        debug('- restored request for', proto);
      }
    });
    requestOverride = [];
  };
  
  function stringifyRequest(options, body) {
    var method = options.method || 'GET';
  
    if (body && typeof(body) !== 'string') {
      body = body.toString();
    }
  
    var port = options.port;
    if (! port) port = (options.proto == 'https' ? '443' : '80');
  
    if (options.proto == 'https' && port == '443' ||
        options.proto == 'http' && port == '80') {
      port = '';
    }
  
    if (port) port = ':' + port;
  
    return method + ' ' + options.proto + '://' + options.hostname + port + options.path + ' ' + body;
  }
  
  function isContentEncoded(headers) {
    if(!headers) {
      return false;
    }
  
    var contentEncoding = headers['content-encoding'];
    return _.isString(contentEncoding) && contentEncoding !== '';
  }
  
  var headersFieldNamesToLowerCase = function(headers) {
    if(!_.isObject(headers)) {
      return headers;
    }
  
    //  For each key in the headers, delete its value and reinsert it with lower-case key.
    //  Keys represent headers field names.
    var lowerCaseHeaders = {};
    _.each(_.keys(headers), function(fieldName) {
      var lowerCaseFieldName = fieldName.toLowerCase();
      if(!_.isUndefined(lowerCaseHeaders[lowerCaseFieldName])) {
        throw new Error('Failed to convert header keys to lower case due to field name conflict: ' + lowerCaseFieldName);
      }
      lowerCaseHeaders[lowerCaseFieldName] = headers[fieldName];
    });
  
    return lowerCaseHeaders;
  };
  
  var headersFieldsArrayToLowerCase = function (headers) {
    return _.uniq(_.map(headers, function (fieldName) {
      return fieldName.toLowerCase();
    }));
  };
  
  /**
   * Deletes the given `fieldName` property from `headers` object by performing
   * case-insensitive search through keys.
   *
   * @headers   {Object} headers - object of header field names and values
   * @fieldName {String} field name - string with the case-insensitive field name
   */
  var deleteHeadersField = function(headers, fieldNameToDelete) {
  
    if(!_.isObject(headers) || !_.isString(fieldNameToDelete)) {
      return;
    }
  
    var lowerCaseFieldNameToDelete = fieldNameToDelete.toLowerCase();
  
    //  Search through the headers and delete all values whose field name matches the given field name.
    _(headers).keys().each(function(fieldName) {
      var lowerCaseFieldName = fieldName.toLowerCase();
      if(lowerCaseFieldName === lowerCaseFieldNameToDelete) {
        delete headers[fieldName];
        //  We don't stop here but continue in order to remove *all* matching field names
        //  (even though if seen regorously there shouldn't be any)
      }
    });
  
  };
  
  function percentEncode(str) {
    return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
      return '%' + c.charCodeAt(0).toString(16).toUpperCase();
    });
  }
  
  exports.normalizeRequestOptions = normalizeRequestOptions;
  exports.isBinaryBuffer = isBinaryBuffer;
  exports.mergeChunks = mergeChunks;
  exports.overrideRequests = overrideRequests;
  exports.restoreOverriddenRequests = restoreOverriddenRequests;
  exports.stringifyRequest = stringifyRequest;
  exports.isContentEncoded = isContentEncoded;
  exports.headersFieldNamesToLowerCase = headersFieldNamesToLowerCase;
  exports.headersFieldsArrayToLowerCase = headersFieldsArrayToLowerCase;
  exports.deleteHeadersField = deleteHeadersField;
  exports.percentEncode = percentEncode;
  
  }).call(this,require("buffer").Buffer)
  },{"buffer":15,"debug":92,"http":44,"https":20,"lodash":99}],4:[function(require,module,exports){
  (function (Buffer,process){
  'use strict';
  
  /**
   * Creates a stream which becomes the response body of the interceptor when a
   * delay is set. The stream outputs the intended body and EOF after the delay.
   *
   * @param  {String|Buffer|Stream} body - the body to write/pipe out
   * @param  {Integer} ms - The delay in milliseconds
   * @constructor
   */
  module.exports = DelayedBody;
  
  var Transform = require('stream').Transform;
  var EventEmitter = require('events').EventEmitter;
  var noop = function () {};
  var util = require('util');
  var timers = require('timers');
  
  function isStream(obj) {
    var is = obj && (typeof a !== 'string') && (! Buffer.isBuffer(obj)) && (typeof obj.setEncoding === 'function');
    return is;
  }
  
  if (!Transform) {
    // for barebones compatibility for node < 0.10
    var FakeTransformStream = function () {
      EventEmitter.call(this);
    };
    util.inherits(FakeTransformStream, EventEmitter);
    FakeTransformStream.prototype.pause = noop;
    FakeTransformStream.prototype.resume = noop;
    FakeTransformStream.prototype.setEncoding = noop;
    FakeTransformStream.prototype.write = function (chunk, encoding) {
      var self = this;
      process.nextTick(function () {
        self.emit('data', chunk, encoding);
      });
    };
    FakeTransformStream.prototype.end = function (chunk) {
      var self = this;
      if (chunk) {
        self.write(chunk);
      }
      process.nextTick(function () {
        self.emit('end');
      });
    };
  
    Transform = FakeTransformStream;
  }
  
  function DelayedBody(ms, body) {
    Transform.call(this);
  
    var self = this;
    var data = '';
    var ended = false;
  
    if (isStream(body)) {
      body.on('data', function (chunk) {
        data += Buffer.isBuffer(chunk) ? chunk.toString() : chunk;
      });
  
      body.once('end', function () {
        ended = true;
      });
  
      body.resume();
    }
  
    setTimeout(function () {
      if (isStream(body) && !ended) {
        body.once('end', function () {
          self.end(data);
        });
      } else {
        self.end(data || body);
      }
    }, ms);
  }
  util.inherits(DelayedBody, Transform);
  
  DelayedBody.prototype._transform = function (chunk, encoding, cb) {
    this.push(chunk);
    process.nextTick(cb);
  };
  }).call(this,{"isBuffer":require("../node_modules/browserify/node_modules/insert-module-globals/node_modules/is-buffer/index.js")},require('_process'))
  },{"../node_modules/browserify/node_modules/insert-module-globals/node_modules/is-buffer/index.js":22,"_process":25,"events":19,"stream":43,"timers":50,"util":54}],5:[function(require,module,exports){
  (function (process){
  'use strict';
  
  /**
   * @module nock/intercepts
   */
  
  var RequestOverrider = require('./request_overrider'),
      common           = require('./common'),
      url              = require('url'),
      inherits         = require('util').inherits,
      http             = require('http'),
      parse            = require('url').parse,
      _                = require('lodash'),
      debug            = require('debug')('nock.intercept'),
      timers           = require('timers'),
      EventEmitter     = require('events').EventEmitter;
  
  
  /**
   * @name NetConnectNotAllowedError
   * @private
   * @desc Error trying to make a connection when disabled external access.
   * @class
   * @example
   * nock.disableNetConnect();
   * http.get('http://zombo.com');
   * // throw NetConnectNotAllowedError
   */
  function NetConnectNotAllowedError(host, path) {
    Error.call(this);
  
    this.name    = 'NetConnectNotAllowedError';
    this.message = 'Nock: Not allow net connect for "' + host + path + '"';
  
    Error.captureStackTrace(this, this.constructor);
  }
  
  inherits(NetConnectNotAllowedError, Error);
  
  var allInterceptors = {},
      allowNetConnect;
  
  /**
   * Enabled real request.
   * @public
   * @param {String|RegExp} matcher=RegExp.new('.*') Expression to match
   * @example
   * // Enables all real requests
   * nock.enableNetConnect();
   * @example
   * // Enables real requests for url that matches google
   * nock.enableNetConnect('google');
   * @example
   * // Enables real requests for url that matches google and amazon
   * nock.enableNetConnect(/(google|amazon)/);
   */
  function enableNetConnect(matcher) {
    if (_.isString(matcher)) {
      allowNetConnect = new RegExp(matcher);
    } else if (_.isObject(matcher) && _.isFunction(matcher.test)) {
      allowNetConnect = matcher;
    } else {
      allowNetConnect = /.*/;
    }
  }
  
  function isEnabledForNetConnect(options) {
    common.normalizeRequestOptions(options);
  
    var enabled = allowNetConnect && allowNetConnect.test(options.host);
    debug('Net connect', enabled ? '' : 'not', 'enabled for', options.host);
    return enabled;
  }
  
  /**
   * Disable all real requests.
   * @public
   * @param {String|RegExp} matcher=RegExp.new('.*') Expression to match
   * @example
   * nock.disableNetConnect();
  */
  function disableNetConnect() {
    allowNetConnect = undefined;
  }
  
  function isOn() {
    return !isOff();
  }
  
  function isOff() {
    return process.env.NOCK_OFF === 'true';
  }
  
  function add(key, interceptor, scope, scopeOptions, host) {
    if (! allInterceptors.hasOwnProperty(key)) {
      allInterceptors[key] = [];
    }
    interceptor.__nock_scope = scope;
  
    //  We need scope's key and scope options for scope filtering function (if defined)
    interceptor.__nock_scopeKey = key;
    interceptor.__nock_scopeOptions = scopeOptions;
    //  We need scope's host for setting correct request headers for filtered scopes.
    interceptor.__nock_scopeHost = host;
    interceptor.interceptionCounter = 0;
  
    allInterceptors[key].push(interceptor);
  }
  
  function remove(interceptor) {
  
    if (interceptor.__nock_scope.shouldPersist()) {
      return;
    }
  
    interceptor.counter -= 1;
    if (interceptor.counter > 0) {
      return;
    }
  
    var key          = interceptor._key.split(' '),
        u            = url.parse(key[1]),
        hostKey      = u.protocol + '//' + u.host,
        interceptors = allInterceptors[hostKey],
        thisInterceptor;
  
    if (interceptors) {
      for(var i = 0; i < interceptors.length; i++) {
        thisInterceptor = interceptors[i];
        if (thisInterceptor === interceptor) {
          interceptors.splice(i, 1);
          break;
        }
      }
  
    }
  }
  
  function removeAll() {
    allInterceptors = {};
  }
  
  function hasHadInterceptors(options) {
    var basePath,
        isBasePathMatched,
        isScopedMatched;
  
    debug('hasHadInterceptors', options.host, options.hostname);
    common.normalizeRequestOptions(options);
  
    basePath = options.proto + '://' + options.host;
  
    debug('looking for interceptors for basepath %j', basePath);
  
    _.each(allInterceptors, function(interceptor, key) {
      if (key === basePath) {
        isBasePathMatched = true;
  
        // false to short circuit the .each
        return false;
      }
  
      _.each(interceptor, function(scope) {
        var filteringScope = scope.__nock_scopeOptions.filteringScope;
  
        //  If scope filtering function is defined and returns a truthy value
        //  then we have to treat this as a match.
        if (filteringScope && filteringScope(basePath)) {
          debug('found matching scope interceptor');
  
          //  Keep the filtered scope (its key) to signal the rest of the module
          //  that this wasn't an exact but filtered match.
          scope.__nock_filteredScope = scope.__nock_scopeKey;
          isScopedMatched = true;
          //  Break out of _.each for scopes.
          return false;
        }
      });
  
      //  Returning falsy value here (which will happen if we have found our matching interceptor)
      //  will break out of _.each for all interceptors.
      return !isScopedMatched;
    });
  
    return (isScopedMatched || isBasePathMatched);
  }
  
  function interceptorsFor(options) {
    var basePath;
  
    common.normalizeRequestOptions(options);
  
    debug('interceptors for %j', options.host);
  
    basePath = options.proto + '://' + options.host;
  
    debug('filtering interceptors for basepath', basePath);
  
    //  First try to use filteringScope if any of the interceptors has it defined.
    var matchingInterceptor;
    _.each(allInterceptors, function(interceptor, key) {
      _.each(interceptor, function(scope) {
        var filteringScope = scope.__nock_scopeOptions.filteringScope;
  
        //  If scope filtering function is defined and returns a truthy value
        //  then we have to treat this as a match.
        if(filteringScope && filteringScope(basePath)) {
          debug('found matching scope interceptor');
  
          //  Keep the filtered scope (its key) to signal the rest of the module
          //  that this wasn't an exact but filtered match.
          scope.__nock_filteredScope = scope.__nock_scopeKey;
          matchingInterceptor = interceptor;
          //  Break out of _.each for scopes.
          return false;
        }
      });
  
      //  Returning falsy value here (which will happen if we have found our matching interceptor)
      //  will break out of _.each for all interceptors.
      return !matchingInterceptor;
    });
  
    if(matchingInterceptor) {
      return matchingInterceptor;
    }
  
    return allInterceptors[basePath] || [];
  }
  
  function removeInterceptor(options) {
    var baseUrl, key, method, proto;
  
    proto = options.proto ? options.proto : 'http';
  
    common.normalizeRequestOptions(options);
    baseUrl = proto + '://' + options.host;
  
    if (allInterceptors[baseUrl] && allInterceptors[baseUrl].length > 0) {
      if (options.path) {
        method = options.method && options.method.toUpperCase() || 'GET';
        key = method + ' ' + baseUrl + (options.path || '/');
  
        for (var i = 0; i < allInterceptors[baseUrl].length; i++) {
          if (allInterceptors[baseUrl][i]._key === key) {
            allInterceptors[baseUrl].splice(i, 1);
            break;
          }
        }
      } else {
        allInterceptors[baseUrl].length = 0;
      }
  
      return true;
    }
  
    return false;
  }
  //  Variable where we keep the ClientRequest we have overridden
  //  (which might or might not be node's original http.ClientRequest)
  var originalClientRequest;
  
  function ErroringClientRequest(error) {
    if (http.OutgoingMessage) http.OutgoingMessage.call(this);
    process.nextTick(function() {
      this.emit('error', error);
    }.bind(this));
  }
  
  if (http.ClientRequest) {
    inherits(ErroringClientRequest, http.ClientRequest);
  }
  
  function overrideClientRequest() {
    debug('Overriding ClientRequest');
  
    if(originalClientRequest) {
      throw new Error('Nock already overrode http.ClientRequest');
    }
  
    // ----- Extending http.ClientRequest
  
    //  Define the overriding client request that nock uses internally.
    function OverriddenClientRequest(options, cb) {
      if (http.OutgoingMessage) http.OutgoingMessage.call(this);
  
      if (isOn() && hasHadInterceptors(options)) {
  
        //  Filter the interceptors per request options.
        var interceptors = interceptorsFor(options);
  
        debug('using', interceptors.length, 'interceptors');
  
        //  Use filtered interceptors to intercept requests.
        var overrider = RequestOverrider(this, options, interceptors, remove, cb);
        for(var propName in overrider) {
          if (overrider.hasOwnProperty(propName)) {
            this[propName] = overrider[propName];
          }
        }
      } else {
        debug('falling back to original ClientRequest');
  
        //  Fallback to original ClientRequest if nock is off or the net connection is enabled.
        if(isOff() || isEnabledForNetConnect(options)) {
          originalClientRequest.apply(this, arguments);
        } else {
          timers.setImmediate(function () {
            var error = new NetConnectNotAllowedError(options.host, options.path);
            this.emit('error', error);
          }.bind(this));
        }
      }
    }
    if (http.ClientRequest) {
      inherits(OverriddenClientRequest, http.ClientRequest);
    } else {
      inherits(OverriddenClientRequest, EventEmitter);
    }
  
    //  Override the http module's request but keep the original so that we can use it and later restore it.
    //  NOTE: We only override http.ClientRequest as https module also uses it.
    originalClientRequest = http.ClientRequest;
    http.ClientRequest = OverriddenClientRequest;
  
    debug('ClientRequest overridden');
  }
  
  function restoreOverriddenClientRequest() {
    debug('restoring overriden ClientRequest');
  
    //  Restore the ClientRequest we have overridden.
    if(!originalClientRequest) {
      debug('- ClientRequest was not overridden');
    } else {
      http.ClientRequest = originalClientRequest;
      originalClientRequest = undefined;
  
      debug('- ClientRequest restored');
    }
  }
  
  function isActive() {
  
    //  If ClientRequest has been overwritten by Nock then originalClientRequest is not undefined.
    //  This means that Nock has been activated.
    return !_.isUndefined(originalClientRequest);
  
  }
  
  function isDone() {
    return _.every(allInterceptors, function(interceptors) {
      return _.every(interceptors, function(interceptor) {
        return interceptor.__nock_scope.isDone();
      });
    });
  }
  
  function pendingMocks() {
    return _.reduce(allInterceptors, function(result, interceptors) {
      for (var interceptor in interceptors) {
        result = result.concat(interceptors[interceptor].__nock_scope.pendingMocks());
      }
  
      return result;
    }, []);
  }
  
  function activate() {
  
    if(originalClientRequest) {
      throw new Error('Nock already active');
    }
  
    overrideClientRequest();
  
    // ----- Overriding http.request and https.request:
  
    common.overrideRequests(function(proto, overriddenRequest, options, callback) {
  
      //  NOTE: overriddenRequest is already bound to its module.
  
      var req,
          res;
  
      if (typeof options === 'string') {
        options = parse(options);
      }
      options.proto = proto;
  
      if (isOn() && hasHadInterceptors(options)) {
  
        var interceptors,
            matches = false,
            allowUnmocked = false;
  
        interceptors = interceptorsFor(options);
  
        interceptors.forEach(function(interceptor) {
          if (! allowUnmocked && interceptor.options.allowUnmocked) { allowUnmocked = true; }
          if (interceptor.matchIndependentOfBody(options)) { matches = true; }
        });
  
        if (! matches && allowUnmocked) {
          if (proto === 'https') {
            var ClientRequest = http.ClientRequest;
            http.ClientRequest = originalClientRequest;
            req = overriddenRequest(options, callback);
            http.ClientRequest = ClientRequest;
          } else {
            req = overriddenRequest(options, callback);
          }
          return req;
        }
  
        //  NOTE: Since we already overrode the http.ClientRequest we are in fact constructing
        //    our own OverriddenClientRequest.
        req = new http.ClientRequest(options);
  
        res = RequestOverrider(req, options, interceptors, remove);
        if (callback) {
          res.on('response', callback);
        }
        return req;
      } else {
        if (isOff() || isEnabledForNetConnect(options)) {
          return overriddenRequest(options, callback);
        } else {
          var error = new NetConnectNotAllowedError(options.host, options.path);
          return new ErroringClientRequest(error);
        }
      }
    });
  
  }
  
  activate();
  
  module.exports = add;
  module.exports.removeAll = removeAll;
  module.exports.removeInterceptor = removeInterceptor;
  module.exports.isOn = isOn;
  module.exports.activate = activate;
  module.exports.isActive = isActive;
  module.exports.isDone = isDone;
  module.exports.pendingMocks = pendingMocks;
  module.exports.enableNetConnect = enableNetConnect;
  module.exports.disableNetConnect = disableNetConnect;
  module.exports.overrideClientRequest = overrideClientRequest;
  module.exports.restoreOverriddenClientRequest = restoreOverriddenClientRequest;
  
  }).call(this,require('_process'))
  },{"./common":3,"./request_overrider":9,"_process":25,"debug":92,"events":19,"http":44,"lodash":99,"timers":50,"url":51,"util":54}],6:[function(require,module,exports){
  (function (Buffer){
  'use strict';
  
  var deepEqual = require('deep-equal');
  var qs = require('querystring');
  
  module.exports =
  function matchBody(spec, body) {
    if (typeof spec === 'undefined') {
      return true;
    }
    var options = this || {};
  
    if (Buffer.isBuffer(body)) {
      body = body.toString();
    }
  
    var contentType = options.headers && (options.headers['Content-Type'] ||
                                          options.headers['content-type']);
  
    var isMultipart = contentType && contentType.toString().match(/multipart/);
  
    //strip line endings from both so that we get a match no matter what OS we are running on
    //if Content-Type does not contains 'multipart'
    if (!isMultipart) {
      body = body.replace(/\r?\n|\r/g, '');
    }
  
    if (spec instanceof RegExp) {
      return body.match(spec);
    }
  
    if (typeof spec === "string") {
      spec = spec.replace(/\r?\n|\r/g, '');
    }
  
    // try to transform body to json
    var json;
    if (typeof spec === 'object' || typeof spec === 'function') {
      try { json = JSON.parse(body);} catch(err) {}
      if (json !== undefined) {
        body = json;
      } else {
        if (contentType && contentType.toString().match(/application\/x-www-form-urlencoded/)) {
          body = qs.parse(body);
        }
      }
    }
  
    if (typeof spec === "function") {
      return spec.call(this, body);
    }
  
    return deepEqual(spec, body, { strict: true });
  };
  
  }).call(this,{"isBuffer":require("../node_modules/browserify/node_modules/insert-module-globals/node_modules/is-buffer/index.js")})
  },{"../node_modules/browserify/node_modules/insert-module-globals/node_modules/is-buffer/index.js":22,"deep-equal":95,"querystring":29}],7:[function(require,module,exports){
  'use strict';
  var _ = require("lodash");
  
  function mixin(a, b) {
  	if (! a) { a = {}; }
  	if (! b) {b = {}; }
  	a = _.cloneDeep(a);
  	for(var prop in b) {
  		a[prop] = b[prop];
  	}
  	return a;
  }
  
  module.exports = mixin;
  
  },{"lodash":99}],8:[function(require,module,exports){
  (function (Buffer){
  'use strict';
  
  var inspect = require('util').inspect;
  var parse = require('url').parse;
  var common = require('./common');
  var intercept = require('./intercept');
  var debug = require('debug')('nock.recorder');
  var _ = require('lodash');
  var Stream = require('stream');
  var URL = require('url');
  
  var SEPARATOR = '\n<<<<<<-- cut here -->>>>>>\n';
  var recordingInProgress = false;
  var outputs = [];
  
  function getScope(options) {
  
    common.normalizeRequestOptions(options);
  
    var scope = [];
    if (options._https_) {
      scope.push('https://');
    } else {
      scope.push('http://');
    }
  
    scope.push(options.host);
  
    //  If a non-standard port wasn't specified in options.host, include it from options.port.
    if(options.host.indexOf(':') === -1 &&
       options.port &&
       ((options._https_ && options.port.toString() !== '443') ||
         (!options._https_ && options.port.toString() !== '80'))) {
      scope.push(':');
      scope.push(options.port);
    }
  
    return scope.join('');
  
  }
  
  function getMethod(options) {
  
    return (options.method || 'GET');
  
  }
  
  var getBodyFromChunks = function(chunks, headers) {
  
    //  If we have headers and there is content-encoding it means that
    //  the body shouldn't be merged but instead persisted as an array
    //  of hex strings so that the responses can be mocked one by one.
    if(common.isContentEncoded(headers)) {
      return _.map(chunks, function(chunk) {
        if(!Buffer.isBuffer(chunk)) {
          if (typeof chunk === 'string') {
            chunk = new Buffer(chunk);
          } else {
            throw new Error('content-encoded responses must all be binary buffers');
          }
        }
  
        return chunk.toString('hex');
      });
    }
  
    var mergedBuffer = common.mergeChunks(chunks);
  
    //  The merged buffer can be one of three things:
    //    1.  A binary buffer which then has to be recorded as a hex string.
    //    2.  A string buffer which represents a JSON object.
    //    3.  A string buffer which doesn't represent a JSON object.
  
    if(common.isBinaryBuffer(mergedBuffer)) {
      return mergedBuffer.toString('hex');
    } else {
      var maybeStringifiedJson = mergedBuffer.toString('utf8');
      try {
        return JSON.parse(maybeStringifiedJson);
      } catch(err) {
        return maybeStringifiedJson;
      }
    }
  
  };
  
  function generateRequestAndResponseObject(req, bodyChunks, options, res, dataChunks) {
  
    options.path = req.path;
    return {
      scope:    getScope(options),
      method:   getMethod(options),
      path:     options.path,
      body:     getBodyFromChunks(bodyChunks),
      status:   res.statusCode,
      response: getBodyFromChunks(dataChunks, res.headers),
      headers:  res.headers,
      reqheaders:   req._headers
    };
  
  }
  
  function generateRequestAndResponse(req, bodyChunks, options, res, dataChunks) {
  
    var requestBody = getBodyFromChunks(bodyChunks);
    var responseBody = getBodyFromChunks(dataChunks, res.headers);
  
    // Remove any query params from options.path so they can be added in the query() function
    var path = options.path;
    var queryIndex = 0;
    var queryObj = {};
    if ((queryIndex = req.path.indexOf('?')) !== -1) {
      path = path.substring(0, queryIndex);
  
      // Create the query() object
      var queries = req.path.slice(queryIndex + 1).split('&');
  
      for (var i = 0; i < queries.length; i++) {
        var query = queries[i].split('=');
        queryObj[query[0]] = query[1];
      }
    }
  
    var ret = [];
    ret.push('\nnock(\'');
    ret.push(getScope(options));
    ret.push('\', ');
    ret.push(JSON.stringify({ encodedQueryParams: true }));
    ret.push(')\n');
    ret.push('  .');
    ret.push(getMethod(options).toLowerCase());
    ret.push('(\'');
    ret.push(path);
    ret.push("'");
    if (requestBody) {
      ret.push(', ');
      ret.push(JSON.stringify(requestBody));
    }
    ret.push(")\n");
    if (req.headers) {
      for (var k in req.headers) {
        ret.push('  .matchHeader(' + JSON.stringify(k) + ', ' + JSON.stringify(req.headers[k]) + ')\n');
      }
    }
  
    if (queryIndex !== -1) {
      ret.push('  .query(');
      ret.push(JSON.stringify(queryObj));
      ret.push(')\n');
    }
  
    ret.push('  .reply(');
    ret.push(res.statusCode.toString());
    ret.push(', ');
    ret.push(JSON.stringify(responseBody));
    if (res.headers) {
      ret.push(', ');
      ret.push(inspect(res.headers));
    }
    ret.push(');\n');
  
    return ret.join('');
  }
  
  //  This module variable is used to identify a unique recording ID in order to skip
  //  spurious requests that sometimes happen. This problem has been, so far,
  //  exclusively detected in nock's unit testing where 'checks if callback is specified'
  //  interferes with other tests as its t.end() is invoked without waiting for request
  //  to finish (which is the point of the test).
  var currentRecordingId = 0;
  
  function record(rec_options) {
  
    //  Set the new current recording ID and capture its value in this instance of record().
    currentRecordingId = currentRecordingId + 1;
    var thisRecordingId = currentRecordingId;
  
    debug('start recording', thisRecordingId, JSON.stringify(rec_options));
  
    //  Trying to start recording with recording already in progress implies an error
    //  in the recording configuration (double recording makes no sense and used to lead
    //  to duplicates in output)
    if(recordingInProgress) {
      throw new Error('Nock recording already in progress');
    }
  
    recordingInProgress = true;
  
    //  Originaly the parameters was a dont_print boolean flag.
    //  To keep the existing code compatible we take that case into account.
    var optionsIsObject = typeof rec_options === 'object';
    var dont_print = (typeof rec_options === 'boolean' && rec_options) ||
        (optionsIsObject && rec_options.dont_print);
    var output_objects = optionsIsObject && rec_options.output_objects;
    var enable_reqheaders_recording = optionsIsObject && rec_options.enable_reqheaders_recording;
    var logging = (optionsIsObject && rec_options.logging) || console.log;
    var use_separator = true;
    if (optionsIsObject && _.has(rec_options, 'use_separator')) {
      use_separator = rec_options.use_separator;
    }
  
    debug(thisRecordingId, 'restoring overridden requests before new overrides');
    //  To preserve backward compatibility (starting recording wasn't throwing if nock was already active)
    //  we restore any requests that may have been overridden by other parts of nock (e.g. intercept)
    //  NOTE: This is hacky as hell but it keeps the backward compatibility *and* allows correct
    //    behavior in the face of other modules also overriding ClientRequest.
    common.restoreOverriddenRequests();
    //  We restore ClientRequest as it messes with recording of modules that also override ClientRequest (e.g. xhr2)
    intercept.restoreOverriddenClientRequest();
  
    //  We override the requests so that we can save information on them before executing.
    common.overrideRequests(function(proto, overriddenRequest, options, callback) {
  
      var bodyChunks = [];
  
      if (typeof options == 'string') {
        var url = URL.parse(options);
        options = {
          hostname: url.hostname,
          method: 'GET',
          port: url.port,
          path: url.path
        };
      }
  
      // Node 0.11 https.request calls http.request -- don't want to record things
      // twice.
      if (options._recording) {
        return overriddenRequest(options, callback);
      }
      options._recording = true;
  
      var req = overriddenRequest(options, function(res) {
  
        debug(thisRecordingId, 'intercepting', proto, 'request to record');
  
        if (typeof options === 'string') {
          options = parse(options);
        }
  
        //  We put our 'end' listener to the front of the listener array.
        res.once('end', function() {
          debug(thisRecordingId, proto, 'intercepted request ended');
  
          var out;
          if(output_objects) {
            out = generateRequestAndResponseObject(req, bodyChunks, options, res, dataChunks);
            if(out.reqheaders) {
              //  We never record user-agent headers as they are worse than useless -
              //  they actually make testing more difficult without providing any benefit (see README)
              common.deleteHeadersField(out.reqheaders, 'user-agent');
  
              //  Remove request headers completely unless it was explicitly enabled by the user (see README)
              if(!enable_reqheaders_recording) {
                delete out.reqheaders;
              }
            }
          } else {
            out = generateRequestAndResponse(req, bodyChunks, options, res, dataChunks);
          }
  
          debug('out:', out);
  
          //  Check that the request was made during the current recording.
          //  If it hasn't then skip it. There is no other simple way to handle
          //  this as it depends on the timing of requests and responses. Throwing
          //  will make some recordings/unit tests faily randomly depending on how
          //  fast/slow the response arrived.
          //  If you are seeing this error then you need to make sure that all
          //  the requests made during a single recording session finish before
          //  ending the same recording session.
          if(thisRecordingId !== currentRecordingId) {
            debug('skipping recording of an out-of-order request', out);
            return;
          }
  
          outputs.push(out);
  
          if (!dont_print) {
            if (use_separator) {
              logging(SEPARATOR + out + SEPARATOR);
            } else {
              logging(out);
            }
          }
        });
  
        var dataChunks = [];
        var encoding;
  
        // We need to be aware of changes to the stream's encoding so that we
        // don't accidentally mangle the data.
        var setEncoding = res.setEncoding;
        res.setEncoding = function (newEncoding) {
          encoding = newEncoding;
          return setEncoding.apply(this, arguments);
        };
  
        //  Give the actual client a chance to setup its listeners.
        //  We will use the listener information to figure out
        //  how we need to feed the intercepted data back to the client.
        if (callback) {
          callback(res, options, callback);
        }
  
        //  Handle clients that listen to 'readable' by intercepting them
        //  and feeding them the data manually.
        var readableListeners = res.listeners('readable');
        if (!_.isEmpty(readableListeners)) {
  
          debug('handle readable listeners');
  
          //  We will replace the client's listeners with our own and manually
          //  invoke them.
          _.each(readableListeners, function(listener) {
            res.removeListener('readable', listener);
          });
  
          //  Repleace the actual Stream.Readable prototype 'read' function
          //  so that we can control what the client listener will be reading.
          var prototypeRead = Stream.Readable.prototype.read;
          var currentReadIndex = 0;
          res.read = function() {
  
            debug(thisRecordingId, 'client reading data on', proto, dataChunks.length);
  
            //  Feed the data to the client through from our collected data chunks.
            if (currentReadIndex < dataChunks.length) {
              debug('chunk', chunk, 'read');
              var chunk = dataChunks[currentReadIndex];
              ++currentReadIndex;
              return chunk;
            } else {
              debug('no more chunks to read');
              return null;
            }
  
          };
  
          //  Put our own listener instead of the removed client listener.
          var onReadable = function(data) {
            debug(thisRecordingId, 'new readable data on', proto);
            var chunk;
            //  Use the prototypeRead function to actually read the data.
            while (null !== (chunk = prototypeRead.call(res))) {
              debug('read', chunk);
              dataChunks.push(chunk);
            }
            //  Manually invoke the user listeners emulating 'readable' event.
            _.each(readableListeners, function(listener) {
              listener();
            });
          };
  
          res.on('readable', onReadable);
  
        } else {
  
          //  In all other cases we (for now at least) fall back on intercepting
          //  'data' events.
          debug('fall back on our original implementation');
  
          //  Since we gave client the chance to setup its listeners
          //  before us, we need to remove them and setup our own.
          var dataListeners = res.listeners('data');
          _.each(dataListeners, function(listener) {
            res.removeListener('data', listener);
          });
  
          var onData = function(data) {
            debug(thisRecordingId, 'new data chunk on', proto);
            if (encoding) {
              data = new Buffer(data, encoding);
            }
            dataChunks.push(data);
            //  Manually invoke the user listeners emulating 'data' event.
            _.each(dataListeners, function(listener) {
              listener(data);
            });
          };
          res.on('data', onData);
        }
  
        debug('finished setting up intercepting');
  
        if (proto === 'https') {
          options._https_ = true;
        }
  
      });
  
      var oldWrite = req.write;
      req.write = function(data, encoding) {
        if ('undefined' !== typeof(data)) {
          if (data) {
            debug(thisRecordingId, 'new', proto, 'body chunk');
            if (! Buffer.isBuffer(data)) {
              data = new Buffer(data, encoding);
            }
            bodyChunks.push(data);
          }
          oldWrite.call(req, data);
        }
      };
  
      return req;
    });
  }
  
  //  Restores *all* the overridden http/https modules' properties.
  function restore() {
    debug(currentRecordingId, 'restoring all the overridden http/https properties');
  
    common.restoreOverriddenRequests();
    intercept.restoreOverriddenClientRequest();
    recordingInProgress = false;
  }
  
  function clear() {
    outputs = [];
  }
  
  exports.record = record;
  exports.outputs = function() {
    return outputs;
  };
  exports.restore = restore;
  exports.clear = clear;
  
  }).call(this,require("buffer").Buffer)
  },{"./common":3,"./intercept":5,"buffer":15,"debug":92,"lodash":99,"stream":43,"url":51,"util":54}],9:[function(require,module,exports){
  (function (process,Buffer){
  'use strict';
  
  var EventEmitter     = require('events').EventEmitter,
      http             = require('http'),
      propagate        = require('propagate'),
      DelayedBody      = require('./delayed_body'),
      IncomingMessage  = http.IncomingMessage,
      ClientRequest    = http.ClientRequest,
      common           = require('./common'),
      Socket           = require('./socket'),
      _                = require('lodash'),
      debug            = require('debug')('nock.request_overrider'),
      timers           = require('timers'),
      ReadableStream   = require('stream').Readable;
  
  function getHeader(request, name) {
    if (!request._headers) {
      return;
    }
  
    var key = name.toLowerCase();
  
    return request._headers[key];
  }
  
  function setHeader(request, name, value) {
    debug('setHeader', name, value);
  
    var key = name.toLowerCase();
  
    request._headers = request._headers || {};
    request._headerNames = request._headerNames || {};
    request._removedHeader = request._removedHeader || {};
  
    request._headers[key] = value;
    request._headerNames[key] = name;
  
    if (name == 'expect' && value == '100-continue') {
      timers.setImmediate(function() {
        debug('continue');
        request.emit('continue');
      });
    }
  }
  
  function isStream(obj) {
    var is = obj && (typeof obj !== 'string') && (!Buffer.isBuffer(obj)) && (typeof obj.setEncoding === 'function');
    return is;
  }
  
  //  Sets request headers of the given request. This is needed during both matching phase
  //  (in case header filters were specified) and mocking phase (to correctly pass mocked
  //  request headers).
  function setRequestHeaders(req, options, interceptor) {
    //  We mock request headers if these were specified.
    if (interceptor.reqheaders) {
      var reqheaders = interceptor.reqheaders;
      _(interceptor.reqheaders).keys().each(function(key) {
        setHeader(req, key, reqheaders[key]);
      });
    }
  
    //  If a filtered scope is being used we have to use scope's host
    //  in the header, otherwise 'host' header won't match.
    //  NOTE: We use lower-case header field names throught Nock.
    var HOST_HEADER = 'host';
    if(interceptor.__nock_filteredScope && interceptor.__nock_scopeHost) {
      if(options && options.headers) {
        options.headers[HOST_HEADER] = interceptor.__nock_scopeHost;
      }
      setHeader(req, HOST_HEADER, interceptor.__nock_scopeHost);
    } else {
      //  For all other cases, we always add host header equal to the
      //  requested host unless it was already defined.
      if (options.host && !getHeader(req, HOST_HEADER)) {
        var hostHeader = options.host;
  
        if (options.port === 80 || options.port === 443) {
          hostHeader = hostHeader.split(':')[0];
        }
  
        setHeader(req, HOST_HEADER, hostHeader);
      }
    }
  
  }
  
  function RequestOverrider(req, options, interceptors, remove, cb) {
  
    var response;
    if (IncomingMessage) {
      response = new IncomingMessage(new EventEmitter());
    } else {
      response = new ReadableStream();
      response._read = function() {};
    }
  
    var requestBodyBuffers = [],
        originalInterceptors = interceptors,
        aborted,
        emitError,
        end,
        ended,
        headers,
        keys,
        key,
        i,
        l;
  
    //  We may be changing the options object and we don't want those
    //  changes affecting the user so we use a clone of the object.
    options = _.clone(options) || {};
  
    response.req = req;
  
    if (options.headers) {
      //  We use lower-case header field names throught Nock.
      options.headers = common.headersFieldNamesToLowerCase(options.headers);
  
      headers = options.headers;
      keys = Object.keys(headers);
  
      for (i = 0, l = keys.length; i < l; i++) {
        key = keys[i];
  
        setHeader(req, key, headers[key]);
      }
    }
  
    /// options.auth
    if (options.auth && (! options.headers || ! options.headers.authorization)) {
      setHeader(req, 'Authorization', 'Basic ' + (new Buffer(options.auth)).toString('base64'));
    }
  
    if (! req.connection) {
      req.connection = new EventEmitter();
    }
  
    req.path = options.path;
  
    options.getHeader = function(name) {
      return getHeader(req, name);
    };
  
    req.socket = response.socket = Socket({ proto: options.proto });
  
    req.write = function(buffer, encoding) {
      debug('write', arguments);
      if (buffer && !aborted) {
        if (! Buffer.isBuffer(buffer)) {
          buffer = new Buffer(buffer, encoding);
        }
        requestBodyBuffers.push(buffer);
      }
      if (aborted) {
        emitError(new Error('Request aborted'));
      }
  
      timers.setImmediate(function() {
        req.emit('drain');
      });
  
      return false;
    };
  
    req.end = function(buffer, encoding) {
      debug('req.end');
      if (!aborted && !ended) {
        req.write(buffer, encoding);
        end(cb);
        req.emit('finish');
        req.emit('end');
      }
      if (aborted) {
        emitError(new Error('Request aborted'));
      }
    };
  
    req.abort = function() {
      debug('req.abort');
      aborted = true;
      if (!ended) {
        end();
      }
      var err = new Error();
      err.code = 'aborted';
      response.emit('close', err);
  
      req.socket.destroy();
    };
  
    // restify listens for a 'socket' event to
    // be emitted before calling end(), which causes
    // nock to hang with restify. The following logic
    // fakes the socket behavior for restify,
    // Fixes: https://github.com/pgte/nock/issues/79
    req.once = req.on = function(event, listener) {
      // emit a fake socket.
      if (event == 'socket') {
        listener(req.socket);
        req.socket.emit('connect', req.socket);
        req.socket.emit('secureConnect', req.socket);
      }
  
      EventEmitter.prototype.on.call(this, event, listener);
      return this;
    };
  
    emitError = function(error) {
      process.nextTick(function () {
        req.emit('error', error);
      });
    };
  
    end = function(cb) {
      debug('ending');
      ended = true;
      var requestBody,
          responseBody,
          responseBuffers,
          interceptor;
  
      //  When request body is a binary buffer we internally use in its hexadecimal representation.
      var requestBodyBuffer = common.mergeChunks(requestBodyBuffers);
      var isBinaryRequestBodyBuffer = common.isBinaryBuffer(requestBodyBuffer);
      if(isBinaryRequestBodyBuffer) {
        requestBody = requestBodyBuffer.toString('hex');
      } else {
        requestBody = requestBodyBuffer.toString('utf8');
      }
  
      /// put back the path into options
      /// because bad behaving agents like superagent
      /// like to change request.path in mid-flight.
      options.path = req.path;
      interceptors = interceptors.filter(function(interceptor) {
        //  For correct matching we need to have correct request headers - if these were specified.
        setRequestHeaders(req, options, interceptor);
  
        return interceptor.match(options, requestBody);
      });
  
      if (interceptors.length < 1) {
        // Try to find a hostname match
        interceptors = originalInterceptors.filter(function(interceptor) {
          return interceptor.match(options, requestBody, true);
        });
        if (interceptors.length && req instanceof ClientRequest) {
          interceptor = interceptors[0];
          if (interceptor.options.allowUnmocked) {
            var newReq = new ClientRequest(options, cb);
            propagate(newReq, req);
            //  We send the raw buffer as we received it, not as we interpreted it.
            newReq.end(requestBodyBuffer);
            return;
          }
        }
  
        var err = new Error("Nock: No match for request " + common.stringifyRequest(options, requestBody));
        err.statusCode = err.status = 404;
        emitError(err);
        return;
      }
  
      debug('interceptor identified, starting mocking');
  
      interceptor = interceptors.shift();
  
      if (typeof interceptor.errorMessage !== 'undefined') {
        interceptor.interceptionCounter++;
        remove(interceptor);
        interceptor.discard();
  
        var error;
        if (_.isObject(interceptor.errorMessage)) {
          error = interceptor.errorMessage;
        } else {
          error = new Error(interceptor.errorMessage);
        }
        timers.setTimeout(emitError, interceptor.delayInMs || 0, error);
        return;
      }
      response.statusCode = Number(interceptor.statusCode) || 200;
      response.headers = interceptor.headers || {};
      response.rawHeaders = interceptor.rawHeaders || [];
      debug('response.rawHeaders:', response.rawHeaders);
  
      //  We again set request headers, now for our matched interceptor.
      setRequestHeaders(req, options, interceptor);
      interceptor.req = req;
      req.headers = req._headers;
  
      if (typeof interceptor.body === 'function') {
        // In case we are waiting for a callback
        if (interceptor.body.length === 3) {
          return interceptor.body(options.path, requestBody || '', continueWithResponseBody);
        }
  
        responseBody = interceptor.body(options.path, requestBody) || '';
  
      } else {
  
        //  If the content is encoded we know that the response body *must* be an array
        //  of response buffers which should be mocked one by one.
        //  (otherwise decompressions after the first one fails as unzip expects to receive
        //  buffer by buffer and not one single merged buffer)
        if(common.isContentEncoded(response.headers) && ! isStream(interceptor.body)) {
  
          if (interceptor.delayInMs) {
            emitError(new Error('Response delay is currently not supported with content-encoded responses.'));
            return;
          }
  
          var buffers = interceptor.body;
          if(!_.isArray(buffers)) {
            emitError(
              new Error(
                'content-encoded response must be an array of binary buffers and not ' + typeof(buffers)));
            return;
          }
  
          responseBuffers = _.map(buffers, function(buffer) {
            return new Buffer(buffer, 'hex');
          });
  
        } else {
  
          responseBody = interceptor.body;
  
          //  If the request was binary then we assume that the response will be binary as well.
          //  In that case we send the response as a Buffer object as that's what the client will expect.
          if(isBinaryRequestBodyBuffer && typeof(responseBody) === 'string') {
            //  Try to create the buffer from the interceptor's body response as hex.
            try {
              responseBody = new Buffer(responseBody, 'hex');
            } catch(err) {
              debug('exception during Buffer construction from hex data:', responseBody, '-', err);
            }
  
            // Creating buffers does not necessarily throw errors, check for difference in size
            if (!responseBody || (interceptor.body.length > 0 && responseBody.length === 0)) {
              //  We fallback on constructing buffer from utf8 representation of the body.
              responseBody = new Buffer(interceptor.body, 'utf8');
            }
          }
        }
      }
  
      return continueWithResponseBody(null, responseBody);
  
      function continueWithResponseBody(err, responseBody) {
        if (err) {
          response.statusCode = 500;
          responseBody = err.stack;
  
        }
  
        //  Transform the response body if it exists (it may not exist
        //  if we have `responseBuffers` instead)
  
        if (responseBody) {
          debug('transform the response body');
  
          if (Array.isArray(responseBody) &&
              responseBody.length == 2 &&
              typeof responseBody[0] == 'number')
          {
            response.statusCode = Number(responseBody[0]);
            responseBody = responseBody[1];
          }
  
          if (interceptor.delayInMs) {
            debug('delaying the response for', interceptor.delayInMs, 'milliseconds');
            responseBody = new DelayedBody(interceptor.delayInMs, responseBody);
          }
  
          if (isStream(responseBody)) {
            debug('response body is a stream');
            responseBody.pause();
            responseBody.on('data', function(d) {
              response.push(d);
            });
            responseBody.on('end', function() {
              response.push(null);
            });
            responseBody.on('error', function(err) {
              response.emit('error', err);
            });
          } else if (responseBody && !Buffer.isBuffer(responseBody)) {
            if (typeof responseBody === 'string') {
              responseBody = new Buffer(responseBody);
            } else {
              responseBody = JSON.stringify(responseBody);
              response.headers['content-type'] = 'application/json';
            }
          }
        }
  
        interceptor.interceptionCounter++;
        remove(interceptor);
        interceptor.discard();
  
        if (aborted) { return; }
  
        /// response.client.authorized = true
        /// fixes https://github.com/pgte/nock/issues/158
        response.client = _.extend(response.client || {}, {
          authorized: true
        });
  
        // Evaluate functional headers.
        Object.keys(response.headers).forEach(function (key) {
          var value = response.headers[key];
  
          if (typeof value === "function") {
            response.headers[key] = value(req, response, responseBody);
          }
        });
  
        for(var rawHeaderIndex = 0 ; rawHeaderIndex < response.rawHeaders.length ; rawHeaderIndex += 2) {
          var value = response.rawHeaders[rawHeaderIndex + 1];
          if (typeof value === "function") {
            response.rawHeaders[rawHeaderIndex + 1] = value(req, response, responseBody);
          }
        }
  
  
        process.nextTick(function() {
          var respond = function() {
            debug('emitting response');
  
            if (typeof cb === 'function') {
              debug('callback with response');
              cb(response);
            }
  
            if (aborted) {
              emitError(new Error('Request aborted'));
            }
            else {
              req.emit('response', response);
            }
  
            if (isStream(responseBody)) {
              debug('resuming response stream');
              responseBody.resume();
            }
            else {
              responseBuffers = responseBuffers || [];
              if (typeof responseBody !== "undefined") {
                debug('adding body to buffer list');
                responseBuffers.push(responseBody);
              }
  
              // Stream the response chunks one at a time.
              timers.setImmediate(function emitChunk() {
                var chunk = responseBuffers.shift();
  
                if (chunk) {
                  debug('emitting response chunk');
                  response.push(chunk);
                  timers.setImmediate(emitChunk);
                }
                else {
                  debug('ending response stream');
                  response.push(null);
                }
              });
            }
          };
  
          if (interceptor.socketDelayInMs && interceptor.socketDelayInMs > 0) {
            req.socket._checkTimeout(interceptor.socketDelayInMs);
          }
  
          if (interceptor.delayConnectionInMs && interceptor.delayConnectionInMs > 0) {
            setTimeout(respond, interceptor.delayConnectionInMs);
          } else {
            respond();
          }
        });
      }
    };
  
    return req;
  }
  
  module.exports = RequestOverrider;
  
  }).call(this,require('_process'),require("buffer").Buffer)
  },{"./common":3,"./delayed_body":4,"./socket":11,"_process":25,"buffer":15,"debug":92,"events":19,"http":44,"lodash":99,"propagate":101,"stream":43,"timers":50}],10:[function(require,module,exports){
  (function (Buffer){
  /* jshint strict:false */
  /**
   * @module nock/scope
   */
  var globalIntercept = require('./intercept')
    , mixin           = require('./mixin')
    , matchBody       = require('./match_body')
    , common          = require('./common')
    , assert          = require('assert')
    , url             = require('url')
    , _               = require('lodash')
    , debug           = require('debug')('nock.scope')
    , stringify       = require('json-stringify-safe');
  
  var fs;
  
  try {
    fs = require('fs');
  } catch(err) {
    // do nothing, we're in the browser
  }
  
  function isStream(obj) {
    return (typeof obj !== 'undefined') &&
           (typeof a !== 'string') &&
           (! Buffer.isBuffer(obj)) &&
           _.isFunction(obj.setEncoding);
  }
  
  function startScope(basePath, options) {
    var interceptors = {},
        scope,
        transformPathFunction,
        transformRequestBodyFunction,
        matchHeaders = [],
        logger = debug,
        scopeOptions = options || {},
        urlParts = url.parse(basePath),
        port = urlParts.port || ((urlParts.protocol === 'http:') ? 80 : 443),
        persist = false,
        contentLen = false,
        date = null,
        basePathname = urlParts.pathname.replace(/\/$/, '');
  
    basePath = urlParts.protocol + '//' + urlParts.hostname + ':' + port;
  
    function add(key, interceptor, scope) {
      if (! interceptors.hasOwnProperty(key)) {
        interceptors[key] = [];
      }
      interceptors[key].push(interceptor);
      globalIntercept(basePath, interceptor, scope, scopeOptions, urlParts.hostname);
    }
  
    function remove(key, interceptor) {
      if (persist) {
        return;
      }
      var arr = interceptors[key];
      if (arr) {
        arr.splice(arr.indexOf(interceptor), 1);
        if (arr.length === 0) { delete interceptors[key]; }
      }
    }
  
    function intercept(uri, method, requestBody, interceptorOptions) {
      var interceptorMatchHeaders = [];
      var key = method.toUpperCase() + ' ' + basePath + basePathname + uri;
  
      function replyWithError(errorMessage) {
        this.errorMessage = errorMessage;
  
        this.options = interceptorOptions || {};
        for (var opt in scopeOptions) {
          if (_.isUndefined(this.options[opt])) {
            this.options[opt] = scopeOptions[opt];
          }
        }
  
        add(key, this, scope, scopeOptions);
        return scope;
      }
  
      function reply(statusCode, body, headers) {
        if (arguments.length <= 2 && _.isFunction(statusCode)) {
          body = statusCode;
          statusCode = 200;
        }
  
        this.statusCode = statusCode;
  
        //  We use lower-case headers throughout Nock.
        headers = common.headersFieldNamesToLowerCase(headers);
  
        this.options = interceptorOptions || {};
        for (var opt in scopeOptions) {
          if (_.isUndefined(this.options[opt])) {
            this.options[opt] = scopeOptions[opt];
          }
        }
  
        if (scope._defaultReplyHeaders) {
          headers = headers || {};
          headers = mixin(scope._defaultReplyHeaders, headers);
        }
  
        if (date) {
          headers = headers || {};
          headers['date'] = date.toUTCString();
        }
  
        if (headers !== undefined) {
          this.headers = {};
          this.rawHeaders = [];
  
          // makes sure all keys in headers are in lower case
          for (var key2 in headers) {
            if (headers.hasOwnProperty(key2)) {
              this.headers[key2.toLowerCase()] = headers[key2];
              this.rawHeaders.push(key2);
              this.rawHeaders.push(headers[key2]);
            }
          }
          debug('reply.rawHeaders:', this.rawHeaders);
        }
  
        //  If the content is not encoded we may need to transform the response body.
        //  Otherwise we leave it as it is.
        if (!common.isContentEncoded(headers)) {
          if (body && typeof(body) !== 'string' &&
              typeof(body) !== 'function' &&
              !Buffer.isBuffer(body) &&
              !isStream(body)) {
            try {
              body = stringify(body);
              if (!this.headers) {
                this.headers = {};
              }
              if (!this.headers['content-type']) {
                this.headers['content-type'] = 'application/json';
              }
              if (contentLen) {
                this.headers['content-length'] = body.length;
              }
            } catch(err) {
              throw new Error('Error encoding response body into JSON');
            }
          }
        }
  
        this.body = body;
  
        add(key, this, scope, scopeOptions);
        return scope;
      }
  
      function replyWithFile(statusCode, filePath, headers) {
        if (! fs) {
          throw new Error('No fs');
        }
        var readStream = fs.createReadStream(filePath);
        readStream.pause();
        this.filePath = filePath;
        return reply.call(this, statusCode, readStream, headers);
      }
  
      var matchStringOrRegexp = function(target, pattern) {
        if (pattern instanceof RegExp) {
          return target.toString().match(pattern);
        } else {
          return target === pattern;
        }
      };
  
      function match(options, body, hostNameOnly) {
        debug('match %s, body = %s', stringify(options), stringify(body));
        if (hostNameOnly) {
          return options.hostname === urlParts.hostname;
        }
  
        var method = options.method || 'GET'
          , path = options.path
          , matches
          , proto = options.proto;
  
        if (transformPathFunction) {
          path = transformPathFunction(path);
        }
        if (typeof(body) !== 'string') {
          body = body.toString();
        }
        if (transformRequestBodyFunction) {
          body = transformRequestBodyFunction(body, this._requestBody);
        }
  
        var checkHeaders = function(header) {
          if (_.isFunction(header.value)) {
            return header.value(options.getHeader(header.name));
          }
          return matchStringOrRegexp(options.getHeader(header.name), header.value);
        };
  
        if (!matchHeaders.every(checkHeaders) ||
            !interceptorMatchHeaders.every(checkHeaders)) {
          logger('headers don\'t match');
          return false;
        }
  
        // Also match request headers
        // https://github.com/pgte/nock/issues/163
        function reqheaderMatches(key) {
          //  We don't try to match request headers if these weren't even specified in the request.
          if (! options.headers) {
            return true;
          }
  
          var reqHeader = this.reqheaders[key];
          var header = options.headers[key];
          if (header && (typeof header !== 'string') && header.toString) {
            header = header.toString();
          }
  
          //  We skip 'host' header comparison unless it's available in both mock and actual request.
          //  This because 'host' may get inserted by Nock itself and then get recorder.
          //  NOTE: We use lower-case header field names throughout Nock.
          if (key === 'host' &&
            (_.isUndefined(header) ||
             _.isUndefined(reqHeader)))
          {
            return true;
          }
  
          if (reqHeader && header) {
            if (_.isFunction(reqHeader)) {
              return reqHeader(header);
            } else if (matchStringOrRegexp(header, reqHeader)) {
              return true;
            }
          }
  
          debug('request header field doesn\'t match:', key, header, reqHeader);
          return false;
        }
  
        var reqHeadersMatch =
          ! this.reqheaders ||
          Object.keys(this.reqheaders).every(reqheaderMatches.bind(this));
  
        if (!reqHeadersMatch) {
          return false;
        }
  
        function reqheaderContains(header) {
          return _.has(options.headers, header);
        }
  
        var reqContainsBadHeaders =
          this.badheaders &&
          _.some(this.badheaders, reqheaderContains);
  
        if (reqContainsBadHeaders) {
          return false;
        }
  
        var matchKey = method.toUpperCase() + ' ';
  
        //  If we have a filtered scope then we use it instead reconstructing
        //  the scope from the request options (proto, host and port) as these
        //  two won't necessarily match and we have to remove the scope that was
        //  matched (vs. that was defined).
        if (this.__nock_filteredScope) {
          matchKey += this.__nock_filteredScope;
        } else {
          matchKey += proto + '://' + options.host;
          if (
               options.port && options.host.indexOf(':') < 0 &&
               (options.port !== 80 || options.proto !== 'http') &&
               (options.port !== 443 || options.proto !== 'https')
             ) {
            matchKey += ":" + options.port;
          }
        }
        matchKey += path;
  
        // Match query strings when using query()
        var matchQueries = true;
        var queryIndex = -1;
        var queries;
        if (this.queries && (queryIndex = matchKey.indexOf('?')) !== -1) {
          queries = matchKey.slice(queryIndex + 1).split('&');
          queries = queries.filter(function(str) {
            return str.length > 0;
          });
  
          // Only check for query string matches if this.queries is an object
          if (_.isObject(this.queries)) {
            // Make sure that you have an equal number of keys. We are
            // looping through the passed query params and not the expected values
            // if the user passes fewer query params than expected but all values
            // match this will throw a false positive. Testing that the length of the
            // passed query params is equal to the length of expected keys will prevent
            // us from doing any value checking BEFORE we know if they have all the proper
            // params
            debug('this.queries: %j', this.queries);
            debug('queries: %j', queries);
            if (Object.keys(this.queries).length !== queries.length) {
              matchQueries = false;
            } else {
              for (var i = 0; i < queries.length; i++) {
                var query = queries[i].split('=');
  
                if (query[1] === undefined || this.queries[ query[0] ] === undefined) {
                  matchQueries = false;
                  break;
                }
  
                var isMatch = matchStringOrRegexp(query[1], this.queries[ query[0] ]);
                matchQueries = matchQueries && !!isMatch;
              }
            }
            debug('matchQueries: %j', matchQueries);
          }
  
          // Remove the query string from the matchKey
          matchKey = matchKey.substr(0, queryIndex);
        }
  
        matches = matchKey === this._key && matchQueries;
  
        // special logger for query()
        if (queryIndex !== -1) {
          logger('matching ' + matchKey + '?' + queries.join('&') + ' to ' + this._key +
                 ' with query(' + stringify(this.queries) + '): ' + matches);
        } else {
          logger('matching ' + matchKey + ' to ' + this._key + ': ' + matches);
        }
  
        if (matches) {
          matches = (matchBody.call(options, this._requestBody, body));
          if (!matches) {
            logger('bodies don\'t match: \n', this._requestBody, '\n', body);
          }
        }
  
        return matches;
      }
  
      function matchIndependentOfBody(options) {
        var method = options.method || 'GET'
          , path = options.path
          , proto = options.proto;
  
        if (transformPathFunction) {
          path = transformPathFunction(path);
        }
  
        var checkHeaders = function(header) {
          return options.getHeader && matchStringOrRegexp(options.getHeader(header.name), header.value);
        };
  
        if (!matchHeaders.every(checkHeaders) ||
            !interceptorMatchHeaders.every(checkHeaders)) {
          return false;
        }
  
        var matchKey = method + ' ' + proto + '://' + options.host + path;
        return this._key === matchKey;
      }
  
      function filteringPath() {
        if (_.isFunction(arguments[0])) {
          this.transformFunction = arguments[0];
        }
        return this;
      }
  
      function discard() {
        if ((persist || this.counter > 0) && this.filePath) {
          this.body = fs.createReadStream(this.filePath);
          this.body.pause();
        }
  
        if (!persist && this.counter < 1) {
          remove(this._key, this);
        }
      }
  
      function matchHeader(name, value) {
        interceptorMatchHeaders.push({ name: name, value: value });
        return this;
      }
  
      function basicAuth(options) {
        var username = options['user'];
        var password = options['pass'] || '';
        var name = 'authorization';
        var value = 'Basic ' + new Buffer(username + ':' + password).toString('base64');
        interceptorMatchHeaders.push({ name: name, value: value });
        return this;
      }
  
      /**
       * Set query strings for the interceptor
       * @name query
       * @param Object Object of query string name,values (accepts regexp values)
       * @public
       * @example
       * // Will match 'http://zombo.com/?q=t'
       * nock('http://zombo.com').get('/').query({q: 't'});
       */
      function query(queries) {
        this.queries = this.queries || {};
  
        // Allow all query strings to match this route
        if (queries === true) {
          this.queries = queries;
        }
  
        for (var q in queries) {
          if (_.isUndefined(this.queries[q])) {
            var value = queries[q];
  
            switch (true) {
            case _.isNumber(value): // fall-though
            case _.isBoolean(value):
              value = value.toString();
              break;
            case _.isUndefined(value): // fall-though
            case _.isNull(value):
              value = '';
              break;
            case _.isString(value):
              if (!scopeOptions.encodedQueryParams) value = common.percentEncode(value);
              break;
            }
  
            if (!scopeOptions.encodedQueryParams) q = common.percentEncode(q);
  
            // everything else, incl. Strings and RegExp values are used 'as-is'
            this.queries[q] = value;
          }
        }
  
        return this;
      }
  
      /**
       * Set number of times will repeat the interceptor
       * @name times
       * @param Integer Number of times to repeat (should be > 0)
       * @public
       * @example
       * // Will repeat mock 5 times for same king of request
       * nock('http://zombo.com).get('/').times(5).reply(200, 'Ok');
      */
      function times(newCounter) {
        if (newCounter < 1) {
          return this;
        }
  
        this.counter = newCounter;
  
        return this;
      }
  
      /**
       * An sugar syntax for times(1)
       * @name once
       * @see {@link times}
       * @public
       * @example
       * nock('http://zombo.com).get('/').once.reply(200, 'Ok');
      */
      function once() {
        return this.times(1);
      }
  
      /**
       * An sugar syntax for times(2)
       * @name twice
       * @see {@link times}
       * @public
       * @example
       * nock('http://zombo.com).get('/').twice.reply(200, 'Ok');
      */
      function twice() {
        return this.times(2);
      }
  
      /**
       * An sugar syntax for times(3).
       * @name thrice
       * @see {@link times}
       * @public
       * @example
       * nock('http://zombo.com).get('/').thrice.reply(200, 'Ok');
      */
      function thrice() {
        return this.times(3);
      }
  
      /**
       * Delay the response by a certain number of ms.
       *
       * @param  {integer} ms - Number of milliseconds to wait
       * @return {scope} - the current scope for chaining
       */
      function delay(ms) {
        this.delayInMs = ms;
        return this;
      }
  
      /**
       * Delay the connection by a certain number of ms.
       *
       * @param  {integer} ms - Number of milliseconds to wait
       * @return {scope} - the current scope for chaining
       */
      function delayConnection(ms) {
        this.delayConnectionInMs = ms;
        return this;
      }
  
      /**
       * Make the socket idle for a certain number of ms (simulated).
       *
       * @param  {integer} ms - Number of milliseconds to wait
       * @return {scope} - the current scope for chaining
       */
      function socketDelay(ms) {
        this.socketDelayInMs = ms;
        return this;
      }
  
      var interceptor = {
          _key: key
        , counter: 1
        , _requestBody: requestBody
        //  We use lower-case header field names throughout Nock.
        , reqheaders: common.headersFieldNamesToLowerCase((options && options.reqheaders) || {})
        , badheaders: common.headersFieldsArrayToLowerCase((options && options.badheaders) || [])
        , reply: reply
        , replyWithError: replyWithError
        , replyWithFile: replyWithFile
        , discard: discard
        , match: match
        , matchIndependentOfBody: matchIndependentOfBody
        , filteringPath: filteringPath
        , matchHeader: matchHeader
        , basicAuth: basicAuth
        , query: query
        , times: times
        , once: once
        , twice: twice
        , thrice: thrice
        , delay: delay
        , delayConnection: delayConnection
        , socketDelay: socketDelay
      };
  
      return interceptor;
    }
  
    function get(uri, requestBody, options) {
      return intercept(uri, 'GET', requestBody, options);
    }
  
    function post(uri, requestBody, options) {
      return intercept(uri, 'POST', requestBody, options);
    }
  
    function put(uri, requestBody, options) {
      return intercept(uri, 'PUT', requestBody, options);
    }
  
    function head(uri, requestBody, options) {
      return intercept(uri, 'HEAD', requestBody, options);
    }
  
    function patch(uri, requestBody, options) {
      return intercept(uri, 'PATCH', requestBody, options);
    }
  
    function merge(uri, requestBody, options) {
      return intercept(uri, 'MERGE', requestBody, options);
    }
  
    function _delete(uri, requestBody, options) {
      return intercept(uri, 'DELETE', requestBody, options);
    }
  
    function pendingMocks() {
      return Object.keys(interceptors);
    }
  
    function isDone() {
  
      // if nock is turned off, it always says it's done
      if (! globalIntercept.isOn()) { return true; }
  
      var keys = Object.keys(interceptors);
      if (keys.length === 0) {
        return true;
      } else {
        var doneHostCount = 0;
  
        keys.forEach(function(key) {
          var doneInterceptorCount = 0;
  
          interceptors[key].forEach(function(interceptor) {
            var isRequireDoneDefined = !_.isUndefined(interceptor.options.requireDone);
            if (isRequireDoneDefined && interceptor.options.requireDone === false) {
              doneInterceptorCount += 1;
            } else if (persist && interceptor.interceptionCounter > 0) {
              doneInterceptorCount += 1;
            }
          });
  
          if (doneInterceptorCount === interceptors[key].length ) {
            doneHostCount += 1;
          }
        });
        return (doneHostCount === keys.length);
      }
    }
  
    function done() {
      assert.ok(isDone(), "Mocks not yet satisfied:\n" + pendingMocks().join("\n"));
    }
  
    function buildFilter() {
      var filteringArguments = arguments;
  
      if (arguments[0] instanceof RegExp) {
        return function(candidate) {
          if (candidate) {
            candidate = candidate.replace(filteringArguments[0], filteringArguments[1]);
          }
          return candidate;
        };
      } else if (_.isFunction(arguments[0])) {
        return arguments[0];
      }
    }
  
    function filteringPath() {
      transformPathFunction = buildFilter.apply(undefined, arguments);
      if (!transformPathFunction) {
        throw new Error('Invalid arguments: filtering path should be a function or a regular expression');
      }
      return this;
    }
  
    function filteringRequestBody() {
      transformRequestBodyFunction = buildFilter.apply(undefined, arguments);
      if (!transformRequestBodyFunction) {
        throw new Error('Invalid arguments: filtering request body should be a function or a regular expression');
      }
      return this;
    }
  
    function matchHeader(name, value) {
      //  We use lower-case header field names throughout Nock.
      matchHeaders.push({ name: name.toLowerCase(), value: value });
      return this;
    }
  
    function defaultReplyHeaders(headers) {
      this._defaultReplyHeaders = common.headersFieldNamesToLowerCase(headers);
      return this;
    }
  
    function log(newLogger) {
      logger = newLogger;
      return this;
    }
  
    function _persist() {
      persist = true;
      return this;
    }
  
    function shouldPersist() {
      return persist;
    }
  
    function replyContentLength() {
      contentLen = true;
      return this;
    }
  
    function replyDate(d) {
      date = d || new Date();
      return this;
    }
  
  
    scope = {
        get: get
      , post: post
      , delete: _delete
      , put: put
      , merge: merge
      , patch: patch
      , head: head
      , intercept: intercept
      , done: done
      , isDone: isDone
      , filteringPath: filteringPath
      , filteringRequestBody: filteringRequestBody
      , matchHeader: matchHeader
      , defaultReplyHeaders: defaultReplyHeaders
      , log: log
      , persist: _persist
      , shouldPersist: shouldPersist
      , pendingMocks: pendingMocks
      , replyContentLength: replyContentLength
      , replyDate: replyDate
    };
  
    return scope;
  }
  
  function cleanAll() {
    globalIntercept.removeAll();
    return module.exports;
  }
  
  function loadDefs(path) {
    if (! fs) {
      throw new Error('No fs');
    }
  
    var contents = fs.readFileSync(path);
    return JSON.parse(contents);
  }
  
  function load(path) {
    return define(loadDefs(path));
  }
  
  function getStatusFromDefinition(nockDef) {
    //  Backward compatibility for when `status` was encoded as string in `reply`.
    if (!_.isUndefined(nockDef.reply)) {
      //  Try parsing `reply` property.
      var parsedReply = parseInt(nockDef.reply, 10);
      if (_.isNumber(parsedReply)) {
        return parsedReply;
      }
    }
  
    var DEFAULT_STATUS_OK = 200;
    return nockDef.status || DEFAULT_STATUS_OK;
  }
  
  function getScopeFromDefinition(nockDef) {
  
    //  Backward compatibility for when `port` was part of definition.
    if (!_.isUndefined(nockDef.port)) {
      //  Include `port` into scope if it doesn't exist.
      var options = url.parse(nockDef.scope);
      if (_.isNull(options.port)) {
        return nockDef.scope + ':' + nockDef.port;
      } else {
        if (parseInt(options.port) !== parseInt(nockDef.port)) {
          throw new Error('Mismatched port numbers in scope and port properties of nock definition.');
        }
      }
    }
  
    return nockDef.scope;
  }
  
  function tryJsonParse(string) {
    try {
      return JSON.parse(string);
    } catch(err) {
      return string;
    }
  }
  
  function define(nockDefs) {
  
    var nocks     = [];
  
    nockDefs.forEach(function(nockDef) {
  
      var nscope     = getScopeFromDefinition(nockDef)
        , npath      = nockDef.path
        , method     = nockDef.method.toLowerCase() || "get"
        , status     = getStatusFromDefinition(nockDef)
        , headers    = nockDef.headers    || {}
        , reqheaders = nockDef.reqheaders || {}
        , body       = nockDef.body       || ''
        , options    = nockDef.options    || {};
  
      //  We use request headers for both filtering (see below) and mocking.
      //  Here we are setting up mocked request headers but we don't want to
      //  be changing the user's options object so we clone it first.
      options = _.clone(options) || {};
      options.reqheaders = reqheaders;
  
      //  Response is not always JSON as it could be a string or binary data or
      //  even an array of binary buffers (e.g. when content is enconded)
      var response;
      if (!nockDef.response) {
        response = '';
      } else {
        response = _.isString(nockDef.response) ? tryJsonParse(nockDef.response) : nockDef.response;
      }
  
      var nock;
      if (body==="*") {
        nock = startScope(nscope, options).filteringRequestBody(function() {
          return "*";
        })[method](npath, "*").reply(status, response, headers);
      } else {
        nock = startScope(nscope, options);
        //  If request headers were specified filter by them.
        if (reqheaders !== {}) {
          for (var k in reqheaders) {
            nock.matchHeader(k, reqheaders[k]);
          }
        }
        if (nockDef.filteringRequestBody) {
          nock.filteringRequestBody(nockDef.filteringRequestBody);
        }
        nock.intercept(npath, method, body).reply(status, response, headers);
      }
  
      nocks.push(nock);
  
    });
  
    return nocks;
  }
  
  
  
  module.exports = startScope;
  
  module.exports.cleanAll = cleanAll;
  module.exports.activate = globalIntercept.activate;
  module.exports.isActive = globalIntercept.isActive;
  module.exports.isDone = globalIntercept.isDone;
  module.exports.pendingMocks = globalIntercept.pendingMocks;
  module.exports.removeInterceptor = globalIntercept.removeInterceptor;
  module.exports.disableNetConnect = globalIntercept.disableNetConnect;
  module.exports.enableNetConnect = globalIntercept.enableNetConnect;
  module.exports.load = load;
  module.exports.loadDefs = loadDefs;
  module.exports.define = define;
  
  }).call(this,require("buffer").Buffer)
  },{"./common":3,"./intercept":5,"./match_body":6,"./mixin":7,"assert":13,"buffer":15,"debug":92,"fs":12,"json-stringify-safe":98,"lodash":99,"url":51}],11:[function(require,module,exports){
  (function (Buffer){
  'use strict';
  
  var EventEmitter = require('events').EventEmitter,
      debug        = require('debug')('nock.socket');
  
  module.exports = Socket;
  
  function Socket(options) {
    var socket = new EventEmitter();
  
    options = options || {};
  
    if (options.proto === 'https') {
      socket.authorized = true;
    }
  
    socket.writable = true;
    socket.readable = true;
  
    socket.setNoDelay = noop;
    socket.setTimeout = function(timeout, fn) {
      this.timeout = timeout;
      this.timeoutFunction = fn;
    }
    socket._checkTimeout = function(delay) {
      if (this.timeout && delay > this.timeout) {
        debug('socket timeout');
        if (this.timeoutFunction) {
          this.timeoutFunction();
        }
        else {
          this.emit('timeout');
        }
      }
    }
  
    socket.setKeepAlive = noop;
    socket.destroy = noop;
    socket.resume = noop;
  
    socket.getPeerCertificate = getPeerCertificate;
  
    return socket;
  }
  
  function noop() {}
  
  function getPeerCertificate() {
    return new Buffer((Math.random() * 10000 + Date.now()).toString()).toString('base64');
  }
  
  }).call(this,require("buffer").Buffer)
  },{"buffer":15,"debug":92,"events":19}],12:[function(require,module,exports){
  
  },{}],13:[function(require,module,exports){
  // http://wiki.commonjs.org/wiki/Unit_Testing/1.0
  //
  // THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
  //
  // Originally from narwhal.js (http://narwhaljs.org)
  // Copyright (c) 2009 Thomas Robinson <280north.com>
  //
  // 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 following conditions:
  //
  // The above copyright notice and this permission notice shall be included in
  // all copies or substantial portions of the Software.
  //
  // 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 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.
  
  // when used in node, this will actually load the util module we depend on
  // versus loading the builtin util module as happens otherwise
  // this is a bug in node module loading as far as I am concerned
  var util = require('util/');
  
  var pSlice = Array.prototype.slice;
  var hasOwn = Object.prototype.hasOwnProperty;
  
  // 1. The assert module provides functions that throw
  // AssertionError's when particular conditions are not met. The
  // assert module must conform to the following interface.
  
  var assert = module.exports = ok;
  
  // 2. The AssertionError is defined in assert.
  // new assert.AssertionError({ message: message,
  //                             actual: actual,
  //                             expected: expected })
  
  assert.AssertionError = function AssertionError(options) {
    this.name = 'AssertionError';
    this.actual = options.actual;
    this.expected = options.expected;
    this.operator = options.operator;
    if (options.message) {
      this.message = options.message;
      this.generatedMessage = false;
    } else {
      this.message = getMessage(this);
      this.generatedMessage = true;
    }
    var stackStartFunction = options.stackStartFunction || fail;
  
    if (Error.captureStackTrace) {
      Error.captureStackTrace(this, stackStartFunction);
    }
    else {
      // non v8 browsers so we can have a stacktrace
      var err = new Error();
      if (err.stack) {
        var out = err.stack;
  
        // try to strip useless frames
        var fn_name = stackStartFunction.name;
        var idx = out.indexOf('\n' + fn_name);
        if (idx >= 0) {
          // once we have located the function frame
          // we need to strip out everything before it (and its line)
          var next_line = out.indexOf('\n', idx + 1);
          out = out.substring(next_line + 1);
        }
  
        this.stack = out;
      }
    }
  };
  
  // assert.AssertionError instanceof Error
  util.inherits(assert.AssertionError, Error);
  
  function replacer(key, value) {
    if (util.isUndefined(value)) {
      return '' + value;
    }
    if (util.isNumber(value) && !isFinite(value)) {
      return value.toString();
    }
    if (util.isFunction(value) || util.isRegExp(value)) {
      return value.toString();
    }
    return value;
  }
  
  function truncate(s, n) {
    if (util.isString(s)) {
      return s.length < n ? s : s.slice(0, n);
    } else {
      return s;
    }
  }
  
  function getMessage(self) {
    return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' +
           self.operator + ' ' +
           truncate(JSON.stringify(self.expected, replacer), 128);
  }
  
  // At present only the three keys mentioned above are used and
  // understood by the spec. Implementations or sub modules can pass
  // other keys to the AssertionError's constructor - they will be
  // ignored.
  
  // 3. All of the following functions must throw an AssertionError
  // when a corresponding condition is not met, with a message that
  // may be undefined if not provided.  All assertion methods provide
  // both the actual and expected values to the assertion error for
  // display purposes.
  
  function fail(actual, expected, message, operator, stackStartFunction) {
    throw new assert.AssertionError({
      message: message,
      actual: actual,
      expected: expected,
      operator: operator,
      stackStartFunction: stackStartFunction
    });
  }
  
  // EXTENSION! allows for well behaved errors defined elsewhere.
  assert.fail = fail;
  
  // 4. Pure assertion tests whether a value is truthy, as determined
  // by !!guard.
  // assert.ok(guard, message_opt);
  // This statement is equivalent to assert.equal(true, !!guard,
  // message_opt);. To test strictly for the value true, use
  // assert.strictEqual(true, guard, message_opt);.
  
  function ok(value, message) {
    if (!value) fail(value, true, message, '==', assert.ok);
  }
  assert.ok = ok;
  
  // 5. The equality assertion tests shallow, coercive equality with
  // ==.
  // assert.equal(actual, expected, message_opt);
  
  assert.equal = function equal(actual, expected, message) {
    if (actual != expected) fail(actual, expected, message, '==', assert.equal);
  };
  
  // 6. The non-equality assertion tests for whether two objects are not equal
  // with != assert.notEqual(actual, expected, message_opt);
  
  assert.notEqual = function notEqual(actual, expected, message) {
    if (actual == expected) {
      fail(actual, expected, message, '!=', assert.notEqual);
    }
  };
  
  // 7. The equivalence assertion tests a deep equality relation.
  // assert.deepEqual(actual, expected, message_opt);
  
  assert.deepEqual = function deepEqual(actual, expected, message) {
    if (!_deepEqual(actual, expected)) {
      fail(actual, expected, message, 'deepEqual', assert.deepEqual);
    }
  };
  
  function _deepEqual(actual, expected) {
    // 7.1. All identical values are equivalent, as determined by ===.
    if (actual === expected) {
      return true;
  
    } else if (util.isBuffer(actual) && util.isBuffer(expected)) {
      if (actual.length != expected.length) return false;
  
      for (var i = 0; i < actual.length; i++) {
        if (actual[i] !== expected[i]) return false;
      }
  
      return true;
  
    // 7.2. If the expected value is a Date object, the actual value is
    // equivalent if it is also a Date object that refers to the same time.
    } else if (util.isDate(actual) && util.isDate(expected)) {
      return actual.getTime() === expected.getTime();
  
    // 7.3 If the expected value is a RegExp object, the actual value is
    // equivalent if it is also a RegExp object with the same source and
    // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
    } else if (util.isRegExp(actual) && util.isRegExp(expected)) {
      return actual.source === expected.source &&
             actual.global === expected.global &&
             actual.multiline === expected.multiline &&
             actual.lastIndex === expected.lastIndex &&
             actual.ignoreCase === expected.ignoreCase;
  
    // 7.4. Other pairs that do not both pass typeof value == 'object',
    // equivalence is determined by ==.
    } else if (!util.isObject(actual) && !util.isObject(expected)) {
      return actual == expected;
  
    // 7.5 For all other Object pairs, including Array objects, equivalence is
    // determined by having the same number of owned properties (as verified
    // with Object.prototype.hasOwnProperty.call), the same set of keys
    // (although not necessarily the same order), equivalent values for every
    // corresponding key, and an identical 'prototype' property. Note: this
    // accounts for both named and indexed properties on Arrays.
    } else {
      return objEquiv(actual, expected);
    }
  }
  
  function isArguments(object) {
    return Object.prototype.toString.call(object) == '[object Arguments]';
  }
  
  function objEquiv(a, b) {
    if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b))
      return false;
    // an identical 'prototype' property.
    if (a.prototype !== b.prototype) return false;
    // if one is a primitive, the other must be same
    if (util.isPrimitive(a) || util.isPrimitive(b)) {
      return a === b;
    }
    var aIsArgs = isArguments(a),
        bIsArgs = isArguments(b);
    if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs))
      return false;
    if (aIsArgs) {
      a = pSlice.call(a);
      b = pSlice.call(b);
      return _deepEqual(a, b);
    }
    var ka = objectKeys(a),
        kb = objectKeys(b),
        key, i;
    // having the same number of owned properties (keys incorporates
    // hasOwnProperty)
    if (ka.length != kb.length)
      return false;
    //the same set of keys (although not necessarily the same order),
    ka.sort();
    kb.sort();
    //~~~cheap key test
    for (i = ka.length - 1; i >= 0; i--) {
      if (ka[i] != kb[i])
        return false;
    }
    //equivalent values for every corresponding key, and
    //~~~possibly expensive deep test
    for (i = ka.length - 1; i >= 0; i--) {
      key = ka[i];
      if (!_deepEqual(a[key], b[key])) return false;
    }
    return true;
  }
  
  // 8. The non-equivalence assertion tests for any deep inequality.
  // assert.notDeepEqual(actual, expected, message_opt);
  
  assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
    if (_deepEqual(actual, expected)) {
      fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
    }
  };
  
  // 9. The strict equality assertion tests strict equality, as determined by ===.
  // assert.strictEqual(actual, expected, message_opt);
  
  assert.strictEqual = function strictEqual(actual, expected, message) {
    if (actual !== expected) {
      fail(actual, expected, message, '===', assert.strictEqual);
    }
  };
  
  // 10. The strict non-equality assertion tests for strict inequality, as
  // determined by !==.  assert.notStrictEqual(actual, expected, message_opt);
  
  assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
    if (actual === expected) {
      fail(actual, expected, message, '!==', assert.notStrictEqual);
    }
  };
  
  function expectedException(actual, expected) {
    if (!actual || !expected) {
      return false;
    }
  
    if (Object.prototype.toString.call(expected) == '[object RegExp]') {
      return expected.test(actual);
    } else if (actual instanceof expected) {
      return true;
    } else if (expected.call({}, actual) === true) {
      return true;
    }
  
    return false;
  }
  
  function _throws(shouldThrow, block, expected, message) {
    var actual;
  
    if (util.isString(expected)) {
      message = expected;
      expected = null;
    }
  
    try {
      block();
    } catch (e) {
      actual = e;
    }
  
    message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
              (message ? ' ' + message : '.');
  
    if (shouldThrow && !actual) {
      fail(actual, expected, 'Missing expected exception' + message);
    }
  
    if (!shouldThrow && expectedException(actual, expected)) {
      fail(actual, expected, 'Got unwanted exception' + message);
    }
  
    if ((shouldThrow && actual && expected &&
        !expectedException(actual, expected)) || (!shouldThrow && actual)) {
      throw actual;
    }
  }
  
  // 11. Expected to throw an error:
  // assert.throws(block, Error_opt, message_opt);
  
  assert.throws = function(block, /*optional*/error, /*optional*/message) {
    _throws.apply(this, [true].concat(pSlice.call(arguments)));
  };
  
  // EXTENSION! This is annoying to write outside this module.
  assert.doesNotThrow = function(block, /*optional*/message) {
    _throws.apply(this, [false].concat(pSlice.call(arguments)));
  };
  
  assert.ifError = function(err) { if (err) {throw err;}};
  
  var objectKeys = Object.keys || function (obj) {
    var keys = [];
    for (var key in obj) {
      if (hasOwn.call(obj, key)) keys.push(key);
    }
    return keys;
  };
  
  },{"util/":54}],14:[function(require,module,exports){
  arguments[4][12][0].apply(exports,arguments)
  },{"dup":12}],15:[function(require,module,exports){
  (function (global){
  /*!
   * The buffer module from node.js, for the browser.
   *
   * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
   * @license  MIT
   */
  /* eslint-disable no-proto */
  
  var base64 = require('base64-js')
  var ieee754 = require('ieee754')
  var isArray = require('isarray')
  
  exports.Buffer = Buffer
  exports.SlowBuffer = SlowBuffer
  exports.INSPECT_MAX_BYTES = 50
  Buffer.poolSize = 8192 // not used by this implementation
  
  var rootParent = {}
  
  /**
   * If `Buffer.TYPED_ARRAY_SUPPORT`:
   *   === true    Use Uint8Array implementation (fastest)
   *   === false   Use Object implementation (most compatible, even IE6)
   *
   * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
   * Opera 11.6+, iOS 4.2+.
   *
   * Due to various browser bugs, sometimes the Object implementation will be used even
   * when the browser supports typed arrays.
   *
   * Note:
   *
   *   - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances,
   *     See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
   *
   *   - Safari 5-7 lacks support for changing the `Object.prototype.constructor` property
   *     on objects.
   *
   *   - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
   *
   *   - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
   *     incorrect length in some situations.
  
   * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they
   * get the Object implementation, which is slower but behaves correctly.
   */
  Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined
    ? global.TYPED_ARRAY_SUPPORT
    : typedArraySupport()
  
  function typedArraySupport () {
    function Bar () {}
    try {
      var arr = new Uint8Array(1)
      arr.foo = function () { return 42 }
      arr.constructor = Bar
      return arr.foo() === 42 && // typed array instances can be augmented
          arr.constructor === Bar && // constructor can be set
          typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
          arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
    } catch (e) {
      return false
    }
  }
  
  function kMaxLength () {
    return Buffer.TYPED_ARRAY_SUPPORT
      ? 0x7fffffff
      : 0x3fffffff
  }
  
  /**
   * Class: Buffer
   * =============
   *
   * The Buffer constructor returns instances of `Uint8Array` that are augmented
   * with function properties for all the node `Buffer` API functions. We use
   * `Uint8Array` so that square bracket notation works as expected -- it returns
   * a single octet.
   *
   * By augmenting the instances, we can avoid modifying the `Uint8Array`
   * prototype.
   */
  function Buffer (arg) {
    if (!(this instanceof Buffer)) {
      // Avoid going through an ArgumentsAdaptorTrampoline in the common case.
      if (arguments.length > 1) return new Buffer(arg, arguments[1])
      return new Buffer(arg)
    }
  
    this.length = 0
    this.parent = undefined
  
    // Common case.
    if (typeof arg === 'number') {
      return fromNumber(this, arg)
    }
  
    // Slightly less common case.
    if (typeof arg === 'string') {
      return fromString(this, arg, arguments.length > 1 ? arguments[1] : 'utf8')
    }
  
    // Unusual.
    return fromObject(this, arg)
  }
  
  function fromNumber (that, length) {
    that = allocate(that, length < 0 ? 0 : checked(length) | 0)
    if (!Buffer.TYPED_ARRAY_SUPPORT) {
      for (var i = 0; i < length; i++) {
        that[i] = 0
      }
    }
    return that
  }
  
  function fromString (that, string, encoding) {
    if (typeof encoding !== 'string' || encoding === '') encoding = 'utf8'
  
    // Assumption: byteLength() return value is always < kMaxLength.
    var length = byteLength(string, encoding) | 0
    that = allocate(that, length)
  
    that.write(string, encoding)
    return that
  }
  
  function fromObject (that, object) {
    if (Buffer.isBuffer(object)) return fromBuffer(that, object)
  
    if (isArray(object)) return fromArray(that, object)
  
    if (object == null) {
      throw new TypeError('must start with number, buffer, array or string')
    }
  
    if (typeof ArrayBuffer !== 'undefined') {
      if (object.buffer instanceof ArrayBuffer) {
        return fromTypedArray(that, object)
      }
      if (object instanceof ArrayBuffer) {
        return fromArrayBuffer(that, object)
      }
    }
  
    if (object.length) return fromArrayLike(that, object)
  
    return fromJsonObject(that, object)
  }
  
  function fromBuffer (that, buffer) {
    var length = checked(buffer.length) | 0
    that = allocate(that, length)
    buffer.copy(that, 0, 0, length)
    return that
  }
  
  function fromArray (that, array) {
    var length = checked(array.length) | 0
    that = allocate(that, length)
    for (var i = 0; i < length; i += 1) {
      that[i] = array[i] & 255
    }
    return that
  }
  
  // Duplicate of fromArray() to keep fromArray() monomorphic.
  function fromTypedArray (that, array) {
    var length = checked(array.length) | 0
    that = allocate(that, length)
    // Truncating the elements is probably not what people expect from typed
    // arrays with BYTES_PER_ELEMENT > 1 but it's compatible with the behavior
    // of the old Buffer constructor.
    for (var i = 0; i < length; i += 1) {
      that[i] = array[i] & 255
    }
    return that
  }
  
  function fromArrayBuffer (that, array) {
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      // Return an augmented `Uint8Array` instance, for best performance
      array.byteLength
      that = Buffer._augment(new Uint8Array(array))
    } else {
      // Fallback: Return an object instance of the Buffer class
      that = fromTypedArray(that, new Uint8Array(array))
    }
    return that
  }
  
  function fromArrayLike (that, array) {
    var length = checked(array.length) | 0
    that = allocate(that, length)
    for (var i = 0; i < length; i += 1) {
      that[i] = array[i] & 255
    }
    return that
  }
  
  // Deserialize { type: 'Buffer', data: [1,2,3,...] } into a Buffer object.
  // Returns a zero-length buffer for inputs that don't conform to the spec.
  function fromJsonObject (that, object) {
    var array
    var length = 0
  
    if (object.type === 'Buffer' && isArray(object.data)) {
      array = object.data
      length = checked(array.length) | 0
    }
    that = allocate(that, length)
  
    for (var i = 0; i < length; i += 1) {
      that[i] = array[i] & 255
    }
    return that
  }
  
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    Buffer.prototype.__proto__ = Uint8Array.prototype
    Buffer.__proto__ = Uint8Array
  }
  
  function allocate (that, length) {
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      // Return an augmented `Uint8Array` instance, for best performance
      that = Buffer._augment(new Uint8Array(length))
      that.__proto__ = Buffer.prototype
    } else {
      // Fallback: Return an object instance of the Buffer class
      that.length = length
      that._isBuffer = true
    }
  
    var fromPool = length !== 0 && length <= Buffer.poolSize >>> 1
    if (fromPool) that.parent = rootParent
  
    return that
  }
  
  function checked (length) {
    // Note: cannot use `length < kMaxLength` here because that fails when
    // length is NaN (which is otherwise coerced to zero.)
    if (length >= kMaxLength()) {
      throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
                           'size: 0x' + kMaxLength().toString(16) + ' bytes')
    }
    return length | 0
  }
  
  function SlowBuffer (subject, encoding) {
    if (!(this instanceof SlowBuffer)) return new SlowBuffer(subject, encoding)
  
    var buf = new Buffer(subject, encoding)
    delete buf.parent
    return buf
  }
  
  Buffer.isBuffer = function isBuffer (b) {
    return !!(b != null && b._isBuffer)
  }
  
  Buffer.compare = function compare (a, b) {
    if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
      throw new TypeError('Arguments must be Buffers')
    }
  
    if (a === b) return 0
  
    var x = a.length
    var y = b.length
  
    var i = 0
    var len = Math.min(x, y)
    while (i < len) {
      if (a[i] !== b[i]) break
  
      ++i
    }
  
    if (i !== len) {
      x = a[i]
      y = b[i]
    }
  
    if (x < y) return -1
    if (y < x) return 1
    return 0
  }
  
  Buffer.isEncoding = function isEncoding (encoding) {
    switch (String(encoding).toLowerCase()) {
      case 'hex':
      case 'utf8':
      case 'utf-8':
      case 'ascii':
      case 'binary':
      case 'base64':
      case 'raw':
      case 'ucs2':
      case 'ucs-2':
      case 'utf16le':
      case 'utf-16le':
        return true
      default:
        return false
    }
  }
  
  Buffer.concat = function concat (list, length) {
    if (!isArray(list)) throw new TypeError('list argument must be an Array of Buffers.')
  
    if (list.length === 0) {
      return new Buffer(0)
    }
  
    var i
    if (length === undefined) {
      length = 0
      for (i = 0; i < list.length; i++) {
        length += list[i].length
      }
    }
  
    var buf = new Buffer(length)
    var pos = 0
    for (i = 0; i < list.length; i++) {
      var item = list[i]
      item.copy(buf, pos)
      pos += item.length
    }
    return buf
  }
  
  function byteLength (string, encoding) {
    if (typeof string !== 'string') string = '' + string
  
    var len = string.length
    if (len === 0) return 0
  
    // Use a for loop to avoid recursion
    var loweredCase = false
    for (;;) {
      switch (encoding) {
        case 'ascii':
        case 'binary':
        // Deprecated
        case 'raw':
        case 'raws':
          return len
        case 'utf8':
        case 'utf-8':
          return utf8ToBytes(string).length
        case 'ucs2':
        case 'ucs-2':
        case 'utf16le':
        case 'utf-16le':
          return len * 2
        case 'hex':
          return len >>> 1
        case 'base64':
          return base64ToBytes(string).length
        default:
          if (loweredCase) return utf8ToBytes(string).length // assume utf8
          encoding = ('' + encoding).toLowerCase()
          loweredCase = true
      }
    }
  }
  Buffer.byteLength = byteLength
  
  // pre-set for values that may exist in the future
  Buffer.prototype.length = undefined
  Buffer.prototype.parent = undefined
  
  function slowToString (encoding, start, end) {
    var loweredCase = false
  
    start = start | 0
    end = end === undefined || end === Infinity ? this.length : end | 0
  
    if (!encoding) encoding = 'utf8'
    if (start < 0) start = 0
    if (end > this.length) end = this.length
    if (end <= start) return ''
  
    while (true) {
      switch (encoding) {
        case 'hex':
          return hexSlice(this, start, end)
  
        case 'utf8':
        case 'utf-8':
          return utf8Slice(this, start, end)
  
        case 'ascii':
          return asciiSlice(this, start, end)
  
        case 'binary':
          return binarySlice(this, start, end)
  
        case 'base64':
          return base64Slice(this, start, end)
  
        case 'ucs2':
        case 'ucs-2':
        case 'utf16le':
        case 'utf-16le':
          return utf16leSlice(this, start, end)
  
        default:
          if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
          encoding = (encoding + '').toLowerCase()
          loweredCase = true
      }
    }
  }
  
  Buffer.prototype.toString = function toString () {
    var length = this.length | 0
    if (length === 0) return ''
    if (arguments.length === 0) return utf8Slice(this, 0, length)
    return slowToString.apply(this, arguments)
  }
  
  Buffer.prototype.equals = function equals (b) {
    if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
    if (this === b) return true
    return Buffer.compare(this, b) === 0
  }
  
  Buffer.prototype.inspect = function inspect () {
    var str = ''
    var max = exports.INSPECT_MAX_BYTES
    if (this.length > 0) {
      str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')
      if (this.length > max) str += ' ... '
    }
    return '<Buffer ' + str + '>'
  }
  
  Buffer.prototype.compare = function compare (b) {
    if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
    if (this === b) return 0
    return Buffer.compare(this, b)
  }
  
  Buffer.prototype.indexOf = function indexOf (val, byteOffset) {
    if (byteOffset > 0x7fffffff) byteOffset = 0x7fffffff
    else if (byteOffset < -0x80000000) byteOffset = -0x80000000
    byteOffset >>= 0
  
    if (this.length === 0) return -1
    if (byteOffset >= this.length) return -1
  
    // Negative offsets start from the end of the buffer
    if (byteOffset < 0) byteOffset = Math.max(this.length + byteOffset, 0)
  
    if (typeof val === 'string') {
      if (val.length === 0) return -1 // special case: looking for empty string always fails
      return String.prototype.indexOf.call(this, val, byteOffset)
    }
    if (Buffer.isBuffer(val)) {
      return arrayIndexOf(this, val, byteOffset)
    }
    if (typeof val === 'number') {
      if (Buffer.TYPED_ARRAY_SUPPORT && Uint8Array.prototype.indexOf === 'function') {
        return Uint8Array.prototype.indexOf.call(this, val, byteOffset)
      }
      return arrayIndexOf(this, [ val ], byteOffset)
    }
  
    function arrayIndexOf (arr, val, byteOffset) {
      var foundIndex = -1
      for (var i = 0; byteOffset + i < arr.length; i++) {
        if (arr[byteOffset + i] === val[foundIndex === -1 ? 0 : i - foundIndex]) {
          if (foundIndex === -1) foundIndex = i
          if (i - foundIndex + 1 === val.length) return byteOffset + foundIndex
        } else {
          foundIndex = -1
        }
      }
      return -1
    }
  
    throw new TypeError('val must be string, number or Buffer')
  }
  
  // `get` is deprecated
  Buffer.prototype.get = function get (offset) {
    console.log('.get() is deprecated. Access using array indexes instead.')
    return this.readUInt8(offset)
  }
  
  // `set` is deprecated
  Buffer.prototype.set = function set (v, offset) {
    console.log('.set() is deprecated. Access using array indexes instead.')
    return this.writeUInt8(v, offset)
  }
  
  function hexWrite (buf, string, offset, length) {
    offset = Number(offset) || 0
    var remaining = buf.length - offset
    if (!length) {
      length = remaining
    } else {
      length = Number(length)
      if (length > remaining) {
        length = remaining
      }
    }
  
    // must be an even number of digits
    var strLen = string.length
    if (strLen % 2 !== 0) throw new Error('Invalid hex string')
  
    if (length > strLen / 2) {
      length = strLen / 2
    }
    for (var i = 0; i < length; i++) {
      var parsed = parseInt(string.substr(i * 2, 2), 16)
      if (isNaN(parsed)) throw new Error('Invalid hex string')
      buf[offset + i] = parsed
    }
    return i
  }
  
  function utf8Write (buf, string, offset, length) {
    return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
  }
  
  function asciiWrite (buf, string, offset, length) {
    return blitBuffer(asciiToBytes(string), buf, offset, length)
  }
  
  function binaryWrite (buf, string, offset, length) {
    return asciiWrite(buf, string, offset, length)
  }
  
  function base64Write (buf, string, offset, length) {
    return blitBuffer(base64ToBytes(string), buf, offset, length)
  }
  
  function ucs2Write (buf, string, offset, length) {
    return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
  }
  
  Buffer.prototype.write = function write (string, offset, length, encoding) {
    // Buffer#write(string)
    if (offset === undefined) {
      encoding = 'utf8'
      length = this.length
      offset = 0
    // Buffer#write(string, encoding)
    } else if (length === undefined && typeof offset === 'string') {
      encoding = offset
      length = this.length
      offset = 0
    // Buffer#write(string, offset[, length][, encoding])
    } else if (isFinite(offset)) {
      offset = offset | 0
      if (isFinite(length)) {
        length = length | 0
        if (encoding === undefined) encoding = 'utf8'
      } else {
        encoding = length
        length = undefined
      }
    // legacy write(string, encoding, offset, length) - remove in v0.13
    } else {
      var swap = encoding
      encoding = offset
      offset = length | 0
      length = swap
    }
  
    var remaining = this.length - offset
    if (length === undefined || length > remaining) length = remaining
  
    if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
      throw new RangeError('attempt to write outside buffer bounds')
    }
  
    if (!encoding) encoding = 'utf8'
  
    var loweredCase = false
    for (;;) {
      switch (encoding) {
        case 'hex':
          return hexWrite(this, string, offset, length)
  
        case 'utf8':
        case 'utf-8':
          return utf8Write(this, string, offset, length)
  
        case 'ascii':
          return asciiWrite(this, string, offset, length)
  
        case 'binary':
          return binaryWrite(this, string, offset, length)
  
        case 'base64':
          // Warning: maxLength not taken into account in base64Write
          return base64Write(this, string, offset, length)
  
        case 'ucs2':
        case 'ucs-2':
        case 'utf16le':
        case 'utf-16le':
          return ucs2Write(this, string, offset, length)
  
        default:
          if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
          encoding = ('' + encoding).toLowerCase()
          loweredCase = true
      }
    }
  }
  
  Buffer.prototype.toJSON = function toJSON () {
    return {
      type: 'Buffer',
      data: Array.prototype.slice.call(this._arr || this, 0)
    }
  }
  
  function base64Slice (buf, start, end) {
    if (start === 0 && end === buf.length) {
      return base64.fromByteArray(buf)
    } else {
      return base64.fromByteArray(buf.slice(start, end))
    }
  }
  
  function utf8Slice (buf, start, end) {
    end = Math.min(buf.length, end)
    var res = []
  
    var i = start
    while (i < end) {
      var firstByte = buf[i]
      var codePoint = null
      var bytesPerSequence = (firstByte > 0xEF) ? 4
        : (firstByte > 0xDF) ? 3
        : (firstByte > 0xBF) ? 2
        : 1
  
      if (i + bytesPerSequence <= end) {
        var secondByte, thirdByte, fourthByte, tempCodePoint
  
        switch (bytesPerSequence) {
          case 1:
            if (firstByte < 0x80) {
              codePoint = firstByte
            }
            break
          case 2:
            secondByte = buf[i + 1]
            if ((secondByte & 0xC0) === 0x80) {
              tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
              if (tempCodePoint > 0x7F) {
                codePoint = tempCodePoint
              }
            }
            break
          case 3:
            secondByte = buf[i + 1]
            thirdByte = buf[i + 2]
            if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
              tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
              if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
                codePoint = tempCodePoint
              }
            }
            break
          case 4:
            secondByte = buf[i + 1]
            thirdByte = buf[i + 2]
            fourthByte = buf[i + 3]
            if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
              tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
              if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
                codePoint = tempCodePoint
              }
            }
        }
      }
  
      if (codePoint === null) {
        // we did not generate a valid codePoint so insert a
        // replacement char (U+FFFD) and advance only 1 byte
        codePoint = 0xFFFD
        bytesPerSequence = 1
      } else if (codePoint > 0xFFFF) {
        // encode to utf16 (surrogate pair dance)
        codePoint -= 0x10000
        res.push(codePoint >>> 10 & 0x3FF | 0xD800)
        codePoint = 0xDC00 | codePoint & 0x3FF
      }
  
      res.push(codePoint)
      i += bytesPerSequence
    }
  
    return decodeCodePointsArray(res)
  }
  
  // Based on http://stackoverflow.com/a/22747272/680742, the browser with
  // the lowest limit is Chrome, with 0x10000 args.
  // We go 1 magnitude less, for safety
  var MAX_ARGUMENTS_LENGTH = 0x1000
  
  function decodeCodePointsArray (codePoints) {
    var len = codePoints.length
    if (len <= MAX_ARGUMENTS_LENGTH) {
      return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
    }
  
    // Decode in chunks to avoid "call stack size exceeded".
    var res = ''
    var i = 0
    while (i < len) {
      res += String.fromCharCode.apply(
        String,
        codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
      )
    }
    return res
  }
  
  function asciiSlice (buf, start, end) {
    var ret = ''
    end = Math.min(buf.length, end)
  
    for (var i = start; i < end; i++) {
      ret += String.fromCharCode(buf[i] & 0x7F)
    }
    return ret
  }
  
  function binarySlice (buf, start, end) {
    var ret = ''
    end = Math.min(buf.length, end)
  
    for (var i = start; i < end; i++) {
      ret += String.fromCharCode(buf[i])
    }
    return ret
  }
  
  function hexSlice (buf, start, end) {
    var len = buf.length
  
    if (!start || start < 0) start = 0
    if (!end || end < 0 || end > len) end = len
  
    var out = ''
    for (var i = start; i < end; i++) {
      out += toHex(buf[i])
    }
    return out
  }
  
  function utf16leSlice (buf, start, end) {
    var bytes = buf.slice(start, end)
    var res = ''
    for (var i = 0; i < bytes.length; i += 2) {
      res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
    }
    return res
  }
  
  Buffer.prototype.slice = function slice (start, end) {
    var len = this.length
    start = ~~start
    end = end === undefined ? len : ~~end
  
    if (start < 0) {
      start += len
      if (start < 0) start = 0
    } else if (start > len) {
      start = len
    }
  
    if (end < 0) {
      end += len
      if (end < 0) end = 0
    } else if (end > len) {
      end = len
    }
  
    if (end < start) end = start
  
    var newBuf
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      newBuf = Buffer._augment(this.subarray(start, end))
    } else {
      var sliceLen = end - start
      newBuf = new Buffer(sliceLen, undefined)
      for (var i = 0; i < sliceLen; i++) {
        newBuf[i] = this[i + start]
      }
    }
  
    if (newBuf.length) newBuf.parent = this.parent || this
  
    return newBuf
  }
  
  /*
   * Need to make sure that buffer isn't trying to write out of bounds.
   */
  function checkOffset (offset, ext, length) {
    if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
    if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
  }
  
  Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkOffset(offset, byteLength, this.length)
  
    var val = this[offset]
    var mul = 1
    var i = 0
    while (++i < byteLength && (mul *= 0x100)) {
      val += this[offset + i] * mul
    }
  
    return val
  }
  
  Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) {
      checkOffset(offset, byteLength, this.length)
    }
  
    var val = this[offset + --byteLength]
    var mul = 1
    while (byteLength > 0 && (mul *= 0x100)) {
      val += this[offset + --byteLength] * mul
    }
  
    return val
  }
  
  Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 1, this.length)
    return this[offset]
  }
  
  Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 2, this.length)
    return this[offset] | (this[offset + 1] << 8)
  }
  
  Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 2, this.length)
    return (this[offset] << 8) | this[offset + 1]
  }
  
  Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return ((this[offset]) |
        (this[offset + 1] << 8) |
        (this[offset + 2] << 16)) +
        (this[offset + 3] * 0x1000000)
  }
  
  Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return (this[offset] * 0x1000000) +
      ((this[offset + 1] << 16) |
      (this[offset + 2] << 8) |
      this[offset + 3])
  }
  
  Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkOffset(offset, byteLength, this.length)
  
    var val = this[offset]
    var mul = 1
    var i = 0
    while (++i < byteLength && (mul *= 0x100)) {
      val += this[offset + i] * mul
    }
    mul *= 0x80
  
    if (val >= mul) val -= Math.pow(2, 8 * byteLength)
  
    return val
  }
  
  Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkOffset(offset, byteLength, this.length)
  
    var i = byteLength
    var mul = 1
    var val = this[offset + --i]
    while (i > 0 && (mul *= 0x100)) {
      val += this[offset + --i] * mul
    }
    mul *= 0x80
  
    if (val >= mul) val -= Math.pow(2, 8 * byteLength)
  
    return val
  }
  
  Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 1, this.length)
    if (!(this[offset] & 0x80)) return (this[offset])
    return ((0xff - this[offset] + 1) * -1)
  }
  
  Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 2, this.length)
    var val = this[offset] | (this[offset + 1] << 8)
    return (val & 0x8000) ? val | 0xFFFF0000 : val
  }
  
  Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 2, this.length)
    var val = this[offset + 1] | (this[offset] << 8)
    return (val & 0x8000) ? val | 0xFFFF0000 : val
  }
  
  Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return (this[offset]) |
      (this[offset + 1] << 8) |
      (this[offset + 2] << 16) |
      (this[offset + 3] << 24)
  }
  
  Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return (this[offset] << 24) |
      (this[offset + 1] << 16) |
      (this[offset + 2] << 8) |
      (this[offset + 3])
  }
  
  Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
    return ieee754.read(this, offset, true, 23, 4)
  }
  
  Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
    return ieee754.read(this, offset, false, 23, 4)
  }
  
  Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 8, this.length)
    return ieee754.read(this, offset, true, 52, 8)
  }
  
  Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 8, this.length)
    return ieee754.read(this, offset, false, 52, 8)
  }
  
  function checkInt (buf, value, offset, ext, max, min) {
    if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance')
    if (value > max || value < min) throw new RangeError('value is out of bounds')
    if (offset + ext > buf.length) throw new RangeError('index out of range')
  }
  
  Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
  
    var mul = 1
    var i = 0
    this[offset] = value & 0xFF
    while (++i < byteLength && (mul *= 0x100)) {
      this[offset + i] = (value / mul) & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
  
    var i = byteLength - 1
    var mul = 1
    this[offset + i] = value & 0xFF
    while (--i >= 0 && (mul *= 0x100)) {
      this[offset + i] = (value / mul) & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
    if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
    this[offset] = (value & 0xff)
    return offset + 1
  }
  
  function objectWriteUInt16 (buf, value, offset, littleEndian) {
    if (value < 0) value = 0xffff + value + 1
    for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) {
      buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
        (littleEndian ? i : 1 - i) * 8
    }
  }
  
  Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value & 0xff)
      this[offset + 1] = (value >>> 8)
    } else {
      objectWriteUInt16(this, value, offset, true)
    }
    return offset + 2
  }
  
  Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 8)
      this[offset + 1] = (value & 0xff)
    } else {
      objectWriteUInt16(this, value, offset, false)
    }
    return offset + 2
  }
  
  function objectWriteUInt32 (buf, value, offset, littleEndian) {
    if (value < 0) value = 0xffffffff + value + 1
    for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) {
      buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
    }
  }
  
  Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset + 3] = (value >>> 24)
      this[offset + 2] = (value >>> 16)
      this[offset + 1] = (value >>> 8)
      this[offset] = (value & 0xff)
    } else {
      objectWriteUInt32(this, value, offset, true)
    }
    return offset + 4
  }
  
  Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 24)
      this[offset + 1] = (value >>> 16)
      this[offset + 2] = (value >>> 8)
      this[offset + 3] = (value & 0xff)
    } else {
      objectWriteUInt32(this, value, offset, false)
    }
    return offset + 4
  }
  
  Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) {
      var limit = Math.pow(2, 8 * byteLength - 1)
  
      checkInt(this, value, offset, byteLength, limit - 1, -limit)
    }
  
    var i = 0
    var mul = 1
    var sub = value < 0 ? 1 : 0
    this[offset] = value & 0xFF
    while (++i < byteLength && (mul *= 0x100)) {
      this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) {
      var limit = Math.pow(2, 8 * byteLength - 1)
  
      checkInt(this, value, offset, byteLength, limit - 1, -limit)
    }
  
    var i = byteLength - 1
    var mul = 1
    var sub = value < 0 ? 1 : 0
    this[offset + i] = value & 0xFF
    while (--i >= 0 && (mul *= 0x100)) {
      this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
    if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
    if (value < 0) value = 0xff + value + 1
    this[offset] = (value & 0xff)
    return offset + 1
  }
  
  Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value & 0xff)
      this[offset + 1] = (value >>> 8)
    } else {
      objectWriteUInt16(this, value, offset, true)
    }
    return offset + 2
  }
  
  Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 8)
      this[offset + 1] = (value & 0xff)
    } else {
      objectWriteUInt16(this, value, offset, false)
    }
    return offset + 2
  }
  
  Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value & 0xff)
      this[offset + 1] = (value >>> 8)
      this[offset + 2] = (value >>> 16)
      this[offset + 3] = (value >>> 24)
    } else {
      objectWriteUInt32(this, value, offset, true)
    }
    return offset + 4
  }
  
  Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
    if (value < 0) value = 0xffffffff + value + 1
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 24)
      this[offset + 1] = (value >>> 16)
      this[offset + 2] = (value >>> 8)
      this[offset + 3] = (value & 0xff)
    } else {
      objectWriteUInt32(this, value, offset, false)
    }
    return offset + 4
  }
  
  function checkIEEE754 (buf, value, offset, ext, max, min) {
    if (value > max || value < min) throw new RangeError('value is out of bounds')
    if (offset + ext > buf.length) throw new RangeError('index out of range')
    if (offset < 0) throw new RangeError('index out of range')
  }
  
  function writeFloat (buf, value, offset, littleEndian, noAssert) {
    if (!noAssert) {
      checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
    }
    ieee754.write(buf, value, offset, littleEndian, 23, 4)
    return offset + 4
  }
  
  Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
    return writeFloat(this, value, offset, true, noAssert)
  }
  
  Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
    return writeFloat(this, value, offset, false, noAssert)
  }
  
  function writeDouble (buf, value, offset, littleEndian, noAssert) {
    if (!noAssert) {
      checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
    }
    ieee754.write(buf, value, offset, littleEndian, 52, 8)
    return offset + 8
  }
  
  Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
    return writeDouble(this, value, offset, true, noAssert)
  }
  
  Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
    return writeDouble(this, value, offset, false, noAssert)
  }
  
  // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
  Buffer.prototype.copy = function copy (target, targetStart, start, end) {
    if (!start) start = 0
    if (!end && end !== 0) end = this.length
    if (targetStart >= target.length) targetStart = target.length
    if (!targetStart) targetStart = 0
    if (end > 0 && end < start) end = start
  
    // Copy 0 bytes; we're done
    if (end === start) return 0
    if (target.length === 0 || this.length === 0) return 0
  
    // Fatal error conditions
    if (targetStart < 0) {
      throw new RangeError('targetStart out of bounds')
    }
    if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds')
    if (end < 0) throw new RangeError('sourceEnd out of bounds')
  
    // Are we oob?
    if (end > this.length) end = this.length
    if (target.length - targetStart < end - start) {
      end = target.length - targetStart + start
    }
  
    var len = end - start
    var i
  
    if (this === target && start < targetStart && targetStart < end) {
      // descending copy from end
      for (i = len - 1; i >= 0; i--) {
        target[i + targetStart] = this[i + start]
      }
    } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
      // ascending copy from start
      for (i = 0; i < len; i++) {
        target[i + targetStart] = this[i + start]
      }
    } else {
      target._set(this.subarray(start, start + len), targetStart)
    }
  
    return len
  }
  
  // fill(value, start=0, end=buffer.length)
  Buffer.prototype.fill = function fill (value, start, end) {
    if (!value) value = 0
    if (!start) start = 0
    if (!end) end = this.length
  
    if (end < start) throw new RangeError('end < start')
  
    // Fill 0 bytes; we're done
    if (end === start) return
    if (this.length === 0) return
  
    if (start < 0 || start >= this.length) throw new RangeError('start out of bounds')
    if (end < 0 || end > this.length) throw new RangeError('end out of bounds')
  
    var i
    if (typeof value === 'number') {
      for (i = start; i < end; i++) {
        this[i] = value
      }
    } else {
      var bytes = utf8ToBytes(value.toString())
      var len = bytes.length
      for (i = start; i < end; i++) {
        this[i] = bytes[i % len]
      }
    }
  
    return this
  }
  
  /**
   * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance.
   * Added in Node 0.12. Only available in browsers that support ArrayBuffer.
   */
  Buffer.prototype.toArrayBuffer = function toArrayBuffer () {
    if (typeof Uint8Array !== 'undefined') {
      if (Buffer.TYPED_ARRAY_SUPPORT) {
        return (new Buffer(this)).buffer
      } else {
        var buf = new Uint8Array(this.length)
        for (var i = 0, len = buf.length; i < len; i += 1) {
          buf[i] = this[i]
        }
        return buf.buffer
      }
    } else {
      throw new TypeError('Buffer.toArrayBuffer not supported in this browser')
    }
  }
  
  // HELPER FUNCTIONS
  // ================
  
  var BP = Buffer.prototype
  
  /**
   * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods
   */
  Buffer._augment = function _augment (arr) {
    arr.constructor = Buffer
    arr._isBuffer = true
  
    // save reference to original Uint8Array set method before overwriting
    arr._set = arr.set
  
    // deprecated
    arr.get = BP.get
    arr.set = BP.set
  
    arr.write = BP.write
    arr.toString = BP.toString
    arr.toLocaleString = BP.toString
    arr.toJSON = BP.toJSON
    arr.equals = BP.equals
    arr.compare = BP.compare
    arr.indexOf = BP.indexOf
    arr.copy = BP.copy
    arr.slice = BP.slice
    arr.readUIntLE = BP.readUIntLE
    arr.readUIntBE = BP.readUIntBE
    arr.readUInt8 = BP.readUInt8
    arr.readUInt16LE = BP.readUInt16LE
    arr.readUInt16BE = BP.readUInt16BE
    arr.readUInt32LE = BP.readUInt32LE
    arr.readUInt32BE = BP.readUInt32BE
    arr.readIntLE = BP.readIntLE
    arr.readIntBE = BP.readIntBE
    arr.readInt8 = BP.readInt8
    arr.readInt16LE = BP.readInt16LE
    arr.readInt16BE = BP.readInt16BE
    arr.readInt32LE = BP.readInt32LE
    arr.readInt32BE = BP.readInt32BE
    arr.readFloatLE = BP.readFloatLE
    arr.readFloatBE = BP.readFloatBE
    arr.readDoubleLE = BP.readDoubleLE
    arr.readDoubleBE = BP.readDoubleBE
    arr.writeUInt8 = BP.writeUInt8
    arr.writeUIntLE = BP.writeUIntLE
    arr.writeUIntBE = BP.writeUIntBE
    arr.writeUInt16LE = BP.writeUInt16LE
    arr.writeUInt16BE = BP.writeUInt16BE
    arr.writeUInt32LE = BP.writeUInt32LE
    arr.writeUInt32BE = BP.writeUInt32BE
    arr.writeIntLE = BP.writeIntLE
    arr.writeIntBE = BP.writeIntBE
    arr.writeInt8 = BP.writeInt8
    arr.writeInt16LE = BP.writeInt16LE
    arr.writeInt16BE = BP.writeInt16BE
    arr.writeInt32LE = BP.writeInt32LE
    arr.writeInt32BE = BP.writeInt32BE
    arr.writeFloatLE = BP.writeFloatLE
    arr.writeFloatBE = BP.writeFloatBE
    arr.writeDoubleLE = BP.writeDoubleLE
    arr.writeDoubleBE = BP.writeDoubleBE
    arr.fill = BP.fill
    arr.inspect = BP.inspect
    arr.toArrayBuffer = BP.toArrayBuffer
  
    return arr
  }
  
  var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g
  
  function base64clean (str) {
    // Node strips out invalid characters like \n and \t from the string, base64-js does not
    str = stringtrim(str).replace(INVALID_BASE64_RE, '')
    // Node converts strings with length < 2 to ''
    if (str.length < 2) return ''
    // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
    while (str.length % 4 !== 0) {
      str = str + '='
    }
    return str
  }
  
  function stringtrim (str) {
    if (str.trim) return str.trim()
    return str.replace(/^\s+|\s+$/g, '')
  }
  
  function toHex (n) {
    if (n < 16) return '0' + n.toString(16)
    return n.toString(16)
  }
  
  function utf8ToBytes (string, units) {
    units = units || Infinity
    var codePoint
    var length = string.length
    var leadSurrogate = null
    var bytes = []
  
    for (var i = 0; i < length; i++) {
      codePoint = string.charCodeAt(i)
  
      // is surrogate component
      if (codePoint > 0xD7FF && codePoint < 0xE000) {
        // last char was a lead
        if (!leadSurrogate) {
          // no lead yet
          if (codePoint > 0xDBFF) {
            // unexpected trail
            if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
            continue
          } else if (i + 1 === length) {
            // unpaired lead
            if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
            continue
          }
  
          // valid lead
          leadSurrogate = codePoint
  
          continue
        }
  
        // 2 leads in a row
        if (codePoint < 0xDC00) {
          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
          leadSurrogate = codePoint
          continue
        }
  
        // valid surrogate pair
        codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000
      } else if (leadSurrogate) {
        // valid bmp char, but last char was a lead
        if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
      }
  
      leadSurrogate = null
  
      // encode utf8
      if (codePoint < 0x80) {
        if ((units -= 1) < 0) break
        bytes.push(codePoint)
      } else if (codePoint < 0x800) {
        if ((units -= 2) < 0) break
        bytes.push(
          codePoint >> 0x6 | 0xC0,
          codePoint & 0x3F | 0x80
        )
      } else if (codePoint < 0x10000) {
        if ((units -= 3) < 0) break
        bytes.push(
          codePoint >> 0xC | 0xE0,
          codePoint >> 0x6 & 0x3F | 0x80,
          codePoint & 0x3F | 0x80
        )
      } else if (codePoint < 0x110000) {
        if ((units -= 4) < 0) break
        bytes.push(
          codePoint >> 0x12 | 0xF0,
          codePoint >> 0xC & 0x3F | 0x80,
          codePoint >> 0x6 & 0x3F | 0x80,
          codePoint & 0x3F | 0x80
        )
      } else {
        throw new Error('Invalid code point')
      }
    }
  
    return bytes
  }
  
  function asciiToBytes (str) {
    var byteArray = []
    for (var i = 0; i < str.length; i++) {
      // Node's code seems to be doing this and not & 0x7F..
      byteArray.push(str.charCodeAt(i) & 0xFF)
    }
    return byteArray
  }
  
  function utf16leToBytes (str, units) {
    var c, hi, lo
    var byteArray = []
    for (var i = 0; i < str.length; i++) {
      if ((units -= 2) < 0) break
  
      c = str.charCodeAt(i)
      hi = c >> 8
      lo = c % 256
      byteArray.push(lo)
      byteArray.push(hi)
    }
  
    return byteArray
  }
  
  function base64ToBytes (str) {
    return base64.toByteArray(base64clean(str))
  }
  
  function blitBuffer (src, dst, offset, length) {
    for (var i = 0; i < length; i++) {
      if ((i + offset >= dst.length) || (i >= src.length)) break
      dst[i + offset] = src[i]
    }
    return i
  }
  
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{"base64-js":16,"ieee754":17,"isarray":18}],16:[function(require,module,exports){
  var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  
  ;(function (exports) {
  	'use strict';
  
    var Arr = (typeof Uint8Array !== 'undefined')
      ? Uint8Array
      : Array
  
  	var PLUS   = '+'.charCodeAt(0)
  	var SLASH  = '/'.charCodeAt(0)
  	var NUMBER = '0'.charCodeAt(0)
  	var LOWER  = 'a'.charCodeAt(0)
  	var UPPER  = 'A'.charCodeAt(0)
  	var PLUS_URL_SAFE = '-'.charCodeAt(0)
  	var SLASH_URL_SAFE = '_'.charCodeAt(0)
  
  	function decode (elt) {
  		var code = elt.charCodeAt(0)
  		if (code === PLUS ||
  		    code === PLUS_URL_SAFE)
  			return 62 // '+'
  		if (code === SLASH ||
  		    code === SLASH_URL_SAFE)
  			return 63 // '/'
  		if (code < NUMBER)
  			return -1 //no match
  		if (code < NUMBER + 10)
  			return code - NUMBER + 26 + 26
  		if (code < UPPER + 26)
  			return code - UPPER
  		if (code < LOWER + 26)
  			return code - LOWER + 26
  	}
  
  	function b64ToByteArray (b64) {
  		var i, j, l, tmp, placeHolders, arr
  
  		if (b64.length % 4 > 0) {
  			throw new Error('Invalid string. Length must be a multiple of 4')
  		}
  
  		// the number of equal signs (place holders)
  		// if there are two placeholders, than the two characters before it
  		// represent one byte
  		// if there is only one, then the three characters before it represent 2 bytes
  		// this is just a cheap hack to not do indexOf twice
  		var len = b64.length
  		placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0
  
  		// base64 is 4/3 + up to two characters of the original data
  		arr = new Arr(b64.length * 3 / 4 - placeHolders)
  
  		// if there are placeholders, only get up to the last complete 4 chars
  		l = placeHolders > 0 ? b64.length - 4 : b64.length
  
  		var L = 0
  
  		function push (v) {
  			arr[L++] = v
  		}
  
  		for (i = 0, j = 0; i < l; i += 4, j += 3) {
  			tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
  			push((tmp & 0xFF0000) >> 16)
  			push((tmp & 0xFF00) >> 8)
  			push(tmp & 0xFF)
  		}
  
  		if (placeHolders === 2) {
  			tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
  			push(tmp & 0xFF)
  		} else if (placeHolders === 1) {
  			tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
  			push((tmp >> 8) & 0xFF)
  			push(tmp & 0xFF)
  		}
  
  		return arr
  	}
  
  	function uint8ToBase64 (uint8) {
  		var i,
  			extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
  			output = "",
  			temp, length
  
  		function encode (num) {
  			return lookup.charAt(num)
  		}
  
  		function tripletToBase64 (num) {
  			return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
  		}
  
  		// go through the array every three bytes, we'll deal with trailing stuff later
  		for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
  			temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
  			output += tripletToBase64(temp)
  		}
  
  		// pad the end with zeros, but make sure to not forget the extra bytes
  		switch (extraBytes) {
  			case 1:
  				temp = uint8[uint8.length - 1]
  				output += encode(temp >> 2)
  				output += encode((temp << 4) & 0x3F)
  				output += '=='
  				break
  			case 2:
  				temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
  				output += encode(temp >> 10)
  				output += encode((temp >> 4) & 0x3F)
  				output += encode((temp << 2) & 0x3F)
  				output += '='
  				break
  		}
  
  		return output
  	}
  
  	exports.toByteArray = b64ToByteArray
  	exports.fromByteArray = uint8ToBase64
  }(typeof exports === 'undefined' ? (this.base64js = {}) : exports))
  
  },{}],17:[function(require,module,exports){
  exports.read = function (buffer, offset, isLE, mLen, nBytes) {
    var e, m
    var eLen = nBytes * 8 - mLen - 1
    var eMax = (1 << eLen) - 1
    var eBias = eMax >> 1
    var nBits = -7
    var i = isLE ? (nBytes - 1) : 0
    var d = isLE ? -1 : 1
    var s = buffer[offset + i]
  
    i += d
  
    e = s & ((1 << (-nBits)) - 1)
    s >>= (-nBits)
    nBits += eLen
    for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
  
    m = e & ((1 << (-nBits)) - 1)
    e >>= (-nBits)
    nBits += mLen
    for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
  
    if (e === 0) {
      e = 1 - eBias
    } else if (e === eMax) {
      return m ? NaN : ((s ? -1 : 1) * Infinity)
    } else {
      m = m + Math.pow(2, mLen)
      e = e - eBias
    }
    return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
  }
  
  exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
    var e, m, c
    var eLen = nBytes * 8 - mLen - 1
    var eMax = (1 << eLen) - 1
    var eBias = eMax >> 1
    var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
    var i = isLE ? 0 : (nBytes - 1)
    var d = isLE ? 1 : -1
    var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
  
    value = Math.abs(value)
  
    if (isNaN(value) || value === Infinity) {
      m = isNaN(value) ? 1 : 0
      e = eMax
    } else {
      e = Math.floor(Math.log(value) / Math.LN2)
      if (value * (c = Math.pow(2, -e)) < 1) {
        e--
        c *= 2
      }
      if (e + eBias >= 1) {
        value += rt / c
      } else {
        value += rt * Math.pow(2, 1 - eBias)
      }
      if (value * c >= 2) {
        e++
        c /= 2
      }
  
      if (e + eBias >= eMax) {
        m = 0
        e = eMax
      } else if (e + eBias >= 1) {
        m = (value * c - 1) * Math.pow(2, mLen)
        e = e + eBias
      } else {
        m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
        e = 0
      }
    }
  
    for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
  
    e = (e << mLen) | m
    eLen += mLen
    for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
  
    buffer[offset + i - d] |= s * 128
  }
  
  },{}],18:[function(require,module,exports){
  var toString = {}.toString;
  
  module.exports = Array.isArray || function (arr) {
    return toString.call(arr) == '[object Array]';
  };
  
  },{}],19:[function(require,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,
  // 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
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // 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.
  
  function EventEmitter() {
    this._events = this._events || {};
    this._maxListeners = this._maxListeners || undefined;
  }
  module.exports = EventEmitter;
  
  // Backwards-compat with node 0.10.x
  EventEmitter.EventEmitter = EventEmitter;
  
  EventEmitter.prototype._events = undefined;
  EventEmitter.prototype._maxListeners = undefined;
  
  // By default EventEmitters will print a warning if more than 10 listeners are
  // added to it. This is a useful default which helps finding memory leaks.
  EventEmitter.defaultMaxListeners = 10;
  
  // Obviously not all Emitters should be limited to 10. This function allows
  // that to be increased. Set to zero for unlimited.
  EventEmitter.prototype.setMaxListeners = function(n) {
    if (!isNumber(n) || n < 0 || isNaN(n))
      throw TypeError('n must be a positive number');
    this._maxListeners = n;
    return this;
  };
  
  EventEmitter.prototype.emit = function(type) {
    var er, handler, len, args, i, listeners;
  
    if (!this._events)
      this._events = {};
  
    // If there is no 'error' event listener then throw.
    if (type === 'error') {
      if (!this._events.error ||
          (isObject(this._events.error) && !this._events.error.length)) {
        er = arguments[1];
        if (er instanceof Error) {
          throw er; // Unhandled 'error' event
        }
        throw TypeError('Uncaught, unspecified "error" event.');
      }
    }
  
    handler = this._events[type];
  
    if (isUndefined(handler))
      return false;
  
    if (isFunction(handler)) {
      switch (arguments.length) {
        // fast cases
        case 1:
          handler.call(this);
          break;
        case 2:
          handler.call(this, arguments[1]);
          break;
        case 3:
          handler.call(this, arguments[1], arguments[2]);
          break;
        // slower
        default:
          args = Array.prototype.slice.call(arguments, 1);
          handler.apply(this, args);
      }
    } else if (isObject(handler)) {
      args = Array.prototype.slice.call(arguments, 1);
      listeners = handler.slice();
      len = listeners.length;
      for (i = 0; i < len; i++)
        listeners[i].apply(this, args);
    }
  
    return true;
  };
  
  EventEmitter.prototype.addListener = function(type, listener) {
    var m;
  
    if (!isFunction(listener))
      throw TypeError('listener must be a function');
  
    if (!this._events)
      this._events = {};
  
    // To avoid recursion in the case that type === "newListener"! Before
    // adding it to the listeners, first emit "newListener".
    if (this._events.newListener)
      this.emit('newListener', type,
                isFunction(listener.listener) ?
                listener.listener : listener);
  
    if (!this._events[type])
      // Optimize the case of one listener. Don't need the extra array object.
      this._events[type] = listener;
    else if (isObject(this._events[type]))
      // If we've already got an array, just append.
      this._events[type].push(listener);
    else
      // Adding the second element, need to change to array.
      this._events[type] = [this._events[type], listener];
  
    // Check for listener leak
    if (isObject(this._events[type]) && !this._events[type].warned) {
      if (!isUndefined(this._maxListeners)) {
        m = this._maxListeners;
      } else {
        m = EventEmitter.defaultMaxListeners;
      }
  
      if (m && m > 0 && this._events[type].length > m) {
        this._events[type].warned = true;
        console.error('(node) warning: possible EventEmitter memory ' +
                      'leak detected. %d listeners added. ' +
                      'Use emitter.setMaxListeners() to increase limit.',
                      this._events[type].length);
        if (typeof console.trace === 'function') {
          // not supported in IE 10
          console.trace();
        }
      }
    }
  
    return this;
  };
  
  EventEmitter.prototype.on = EventEmitter.prototype.addListener;
  
  EventEmitter.prototype.once = function(type, listener) {
    if (!isFunction(listener))
      throw TypeError('listener must be a function');
  
    var fired = false;
  
    function g() {
      this.removeListener(type, g);
  
      if (!fired) {
        fired = true;
        listener.apply(this, arguments);
      }
    }
  
    g.listener = listener;
    this.on(type, g);
  
    return this;
  };
  
  // emits a 'removeListener' event iff the listener was removed
  EventEmitter.prototype.removeListener = function(type, listener) {
    var list, position, length, i;
  
    if (!isFunction(listener))
      throw TypeError('listener must be a function');
  
    if (!this._events || !this._events[type])
      return this;
  
    list = this._events[type];
    length = list.length;
    position = -1;
  
    if (list === listener ||
        (isFunction(list.listener) && list.listener === listener)) {
      delete this._events[type];
      if (this._events.removeListener)
        this.emit('removeListener', type, listener);
  
    } else if (isObject(list)) {
      for (i = length; i-- > 0;) {
        if (list[i] === listener ||
            (list[i].listener && list[i].listener === listener)) {
          position = i;
          break;
        }
      }
  
      if (position < 0)
        return this;
  
      if (list.length === 1) {
        list.length = 0;
        delete this._events[type];
      } else {
        list.splice(position, 1);
      }
  
      if (this._events.removeListener)
        this.emit('removeListener', type, listener);
    }
  
    return this;
  };
  
  EventEmitter.prototype.removeAllListeners = function(type) {
    var key, listeners;
  
    if (!this._events)
      return this;
  
    // not listening for removeListener, no need to emit
    if (!this._events.removeListener) {
      if (arguments.length === 0)
        this._events = {};
      else if (this._events[type])
        delete this._events[type];
      return this;
    }
  
    // emit removeListener for all listeners on all events
    if (arguments.length === 0) {
      for (key in this._events) {
        if (key === 'removeListener') continue;
        this.removeAllListeners(key);
      }
      this.removeAllListeners('removeListener');
      this._events = {};
      return this;
    }
  
    listeners = this._events[type];
  
    if (isFunction(listeners)) {
      this.removeListener(type, listeners);
    } else if (listeners) {
      // LIFO order
      while (listeners.length)
        this.removeListener(type, listeners[listeners.length - 1]);
    }
    delete this._events[type];
  
    return this;
  };
  
  EventEmitter.prototype.listeners = function(type) {
    var ret;
    if (!this._events || !this._events[type])
      ret = [];
    else if (isFunction(this._events[type]))
      ret = [this._events[type]];
    else
      ret = this._events[type].slice();
    return ret;
  };
  
  EventEmitter.prototype.listenerCount = function(type) {
    if (this._events) {
      var evlistener = this._events[type];
  
      if (isFunction(evlistener))
        return 1;
      else if (evlistener)
        return evlistener.length;
    }
    return 0;
  };
  
  EventEmitter.listenerCount = function(emitter, type) {
    return emitter.listenerCount(type);
  };
  
  function isFunction(arg) {
    return typeof arg === 'function';
  }
  
  function isNumber(arg) {
    return typeof arg === 'number';
  }
  
  function isObject(arg) {
    return typeof arg === 'object' && arg !== null;
  }
  
  function isUndefined(arg) {
    return arg === void 0;
  }
  
  },{}],20:[function(require,module,exports){
  var http = require('http');
  
  var https = module.exports;
  
  for (var key in http) {
      if (http.hasOwnProperty(key)) https[key] = http[key];
  };
  
  https.request = function (params, cb) {
      if (!params) params = {};
      params.scheme = 'https';
      params.protocol = 'https:';
      return http.request.call(this, params, cb);
  }
  
  },{"http":44}],21:[function(require,module,exports){
  if (typeof Object.create === 'function') {
    // implementation from standard node.js 'util' module
    module.exports = function inherits(ctor, superCtor) {
      ctor.super_ = superCtor
      ctor.prototype = Object.create(superCtor.prototype, {
        constructor: {
          value: ctor,
          enumerable: false,
          writable: true,
          configurable: true
        }
      });
    };
  } else {
    // old school shim for old browsers
    module.exports = function inherits(ctor, superCtor) {
      ctor.super_ = superCtor
      var TempCtor = function () {}
      TempCtor.prototype = superCtor.prototype
      ctor.prototype = new TempCtor()
      ctor.prototype.constructor = ctor
    }
  }
  
  },{}],22:[function(require,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))
      ))
  }
  
  },{}],23:[function(require,module,exports){
  module.exports = Array.isArray || function (arr) {
    return Object.prototype.toString.call(arr) == '[object Array]';
  };
  
  },{}],24:[function(require,module,exports){
  (function (process){
  // 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
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // 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.
  
  // resolves . and .. elements in a path array with directory names there
  // must be no slashes, empty elements, or device names (c:\) in the array
  // (so also no leading and trailing slashes - it does not distinguish
  // relative and absolute paths)
  function normalizeArray(parts, allowAboveRoot) {
    // if the path tries to go above the root, `up` ends up > 0
    var up = 0;
    for (var i = parts.length - 1; i >= 0; i--) {
      var last = parts[i];
      if (last === '.') {
        parts.splice(i, 1);
      } else if (last === '..') {
        parts.splice(i, 1);
        up++;
      } else if (up) {
        parts.splice(i, 1);
        up--;
      }
    }
  
    // if the path is allowed to go above the root, restore leading ..s
    if (allowAboveRoot) {
      for (; up--; up) {
        parts.unshift('..');
      }
    }
  
    return parts;
  }
  
  // Split a filename into [root, dir, basename, ext], unix version
  // 'root' is just a slash, or nothing.
  var splitPathRe =
      /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
  var splitPath = function(filename) {
    return splitPathRe.exec(filename).slice(1);
  };
  
  // path.resolve([from ...], to)
  // posix version
  exports.resolve = function() {
    var resolvedPath = '',
        resolvedAbsolute = false;
  
    for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
      var path = (i >= 0) ? arguments[i] : process.cwd();
  
      // Skip empty and invalid entries
      if (typeof path !== 'string') {
        throw new TypeError('Arguments to path.resolve must be strings');
      } else if (!path) {
        continue;
      }
  
      resolvedPath = path + '/' + resolvedPath;
      resolvedAbsolute = path.charAt(0) === '/';
    }
  
    // At this point the path should be resolved to a full absolute path, but
    // handle relative paths to be safe (might happen when process.cwd() fails)
  
    // Normalize the path
    resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
      return !!p;
    }), !resolvedAbsolute).join('/');
  
    return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
  };
  
  // path.normalize(path)
  // posix version
  exports.normalize = function(path) {
    var isAbsolute = exports.isAbsolute(path),
        trailingSlash = substr(path, -1) === '/';
  
    // Normalize the path
    path = normalizeArray(filter(path.split('/'), function(p) {
      return !!p;
    }), !isAbsolute).join('/');
  
    if (!path && !isAbsolute) {
      path = '.';
    }
    if (path && trailingSlash) {
      path += '/';
    }
  
    return (isAbsolute ? '/' : '') + path;
  };
  
  // posix version
  exports.isAbsolute = function(path) {
    return path.charAt(0) === '/';
  };
  
  // posix version
  exports.join = function() {
    var paths = Array.prototype.slice.call(arguments, 0);
    return exports.normalize(filter(paths, function(p, index) {
      if (typeof p !== 'string') {
        throw new TypeError('Arguments to path.join must be strings');
      }
      return p;
    }).join('/'));
  };
  
  
  // path.relative(from, to)
  // posix version
  exports.relative = function(from, to) {
    from = exports.resolve(from).substr(1);
    to = exports.resolve(to).substr(1);
  
    function trim(arr) {
      var start = 0;
      for (; start < arr.length; start++) {
        if (arr[start] !== '') break;
      }
  
      var end = arr.length - 1;
      for (; end >= 0; end--) {
        if (arr[end] !== '') break;
      }
  
      if (start > end) return [];
      return arr.slice(start, end - start + 1);
    }
  
    var fromParts = trim(from.split('/'));
    var toParts = trim(to.split('/'));
  
    var length = Math.min(fromParts.length, toParts.length);
    var samePartsLength = length;
    for (var i = 0; i < length; i++) {
      if (fromParts[i] !== toParts[i]) {
        samePartsLength = i;
        break;
      }
    }
  
    var outputParts = [];
    for (var i = samePartsLength; i < fromParts.length; i++) {
      outputParts.push('..');
    }
  
    outputParts = outputParts.concat(toParts.slice(samePartsLength));
  
    return outputParts.join('/');
  };
  
  exports.sep = '/';
  exports.delimiter = ':';
  
  exports.dirname = function(path) {
    var result = splitPath(path),
        root = result[0],
        dir = result[1];
  
    if (!root && !dir) {
      // No dirname whatsoever
      return '.';
    }
  
    if (dir) {
      // It has a dirname, strip trailing slash
      dir = dir.substr(0, dir.length - 1);
    }
  
    return root + dir;
  };
  
  
  exports.basename = function(path, ext) {
    var f = splitPath(path)[2];
    // TODO: make this comparison case-insensitive on windows?
    if (ext && f.substr(-1 * ext.length) === ext) {
      f = f.substr(0, f.length - ext.length);
    }
    return f;
  };
  
  
  exports.extname = function(path) {
    return splitPath(path)[3];
  };
  
  function filter (xs, f) {
      if (xs.filter) return xs.filter(f);
      var res = [];
      for (var i = 0; i < xs.length; i++) {
          if (f(xs[i], i, xs)) res.push(xs[i]);
      }
      return res;
  }
  
  // String.prototype.substr - negative index don't work in IE8
  var substr = 'ab'.substr(-1) === 'b'
      ? function (str, start, len) { return str.substr(start, len) }
      : function (str, start, len) {
          if (start < 0) start = str.length + start;
          return str.substr(start, len);
      }
  ;
  
  }).call(this,require('_process'))
  },{"_process":25}],25:[function(require,module,exports){
  // shim for using process in browser
  
  var process = module.exports = {};
  var queue = [];
  var draining = false;
  var currentQueue;
  var queueIndex = -1;
  
  function cleanUpNextTick() {
      draining = false;
      if (currentQueue.length) {
          queue = currentQueue.concat(queue);
      } else {
          queueIndex = -1;
      }
      if (queue.length) {
          drainQueue();
      }
  }
  
  function drainQueue() {
      if (draining) {
          return;
      }
      var timeout = setTimeout(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;
      clearTimeout(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) {
          setTimeout(drainQueue, 0);
      }
  };
  
  // v8 likes predictible objects
  function Item(fun, array) {
      this.fun = fun;
      this.array = array;
  }
  Item.prototype.run = function () {
      this.fun.apply(null, this.array);
  };
  process.title = 'browser';
  process.browser = true;
  process.env = {};
  process.argv = [];
  process.version = ''; // empty string to avoid regexp issues
  process.versions = {};
  
  function noop() {}
  
  process.on = noop;
  process.addListener = noop;
  process.once = noop;
  process.off = noop;
  process.removeListener = noop;
  process.removeAllListeners = noop;
  process.emit = noop;
  
  process.binding = function (name) {
      throw new Error('process.binding is not supported');
  };
  
  process.cwd = function () { return '/' };
  process.chdir = function (dir) {
      throw new Error('process.chdir is not supported');
  };
  process.umask = function() { return 0; };
  
  },{}],26:[function(require,module,exports){
  (function (global){
  /*! https://mths.be/punycode v1.4.0 by @mathias */
  ;(function(root) {
  
  	/** Detect free variables */
  	var freeExports = typeof exports == 'object' && exports &&
  		!exports.nodeType && exports;
  	var freeModule = typeof module == 'object' && module &&
  		!module.nodeType && module;
  	var freeGlobal = typeof global == 'object' && global;
  	if (
  		freeGlobal.global === freeGlobal ||
  		freeGlobal.window === freeGlobal ||
  		freeGlobal.self === freeGlobal
  	) {
  		root = freeGlobal;
  	}
  
  	/**
  	 * The `punycode` object.
  	 * @name punycode
  	 * @type Object
  	 */
  	var punycode,
  
  	/** Highest positive signed 32-bit float value */
  	maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
  
  	/** Bootstring parameters */
  	base = 36,
  	tMin = 1,
  	tMax = 26,
  	skew = 38,
  	damp = 700,
  	initialBias = 72,
  	initialN = 128, // 0x80
  	delimiter = '-', // '\x2D'
  
  	/** Regular expressions */
  	regexPunycode = /^xn--/,
  	regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
  	regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
  
  	/** Error messages */
  	errors = {
  		'overflow': 'Overflow: input needs wider integers to process',
  		'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
  		'invalid-input': 'Invalid input'
  	},
  
  	/** Convenience shortcuts */
  	baseMinusTMin = base - tMin,
  	floor = Math.floor,
  	stringFromCharCode = String.fromCharCode,
  
  	/** Temporary variable */
  	key;
  
  	/*--------------------------------------------------------------------------*/
  
  	/**
  	 * A generic error utility function.
  	 * @private
  	 * @param {String} type The error type.
  	 * @returns {Error} Throws a `RangeError` with the applicable error message.
  	 */
  	function error(type) {
  		throw new RangeError(errors[type]);
  	}
  
  	/**
  	 * A generic `Array#map` utility function.
  	 * @private
  	 * @param {Array} array The array to iterate over.
  	 * @param {Function} callback The function that gets called for every array
  	 * item.
  	 * @returns {Array} A new array of values returned by the callback function.
  	 */
  	function map(array, fn) {
  		var length = array.length;
  		var result = [];
  		while (length--) {
  			result[length] = fn(array[length]);
  		}
  		return result;
  	}
  
  	/**
  	 * A simple `Array#map`-like wrapper to work with domain name strings or email
  	 * addresses.
  	 * @private
  	 * @param {String} domain The domain name or email address.
  	 * @param {Function} callback The function that gets called for every
  	 * character.
  	 * @returns {Array} A new string of characters returned by the callback
  	 * function.
  	 */
  	function mapDomain(string, fn) {
  		var parts = string.split('@');
  		var result = '';
  		if (parts.length > 1) {
  			// In email addresses, only the domain name should be punycoded. Leave
  			// the local part (i.e. everything up to `@`) intact.
  			result = parts[0] + '@';
  			string = parts[1];
  		}
  		// Avoid `split(regex)` for IE8 compatibility. See #17.
  		string = string.replace(regexSeparators, '\x2E');
  		var labels = string.split('.');
  		var encoded = map(labels, fn).join('.');
  		return result + encoded;
  	}
  
  	/**
  	 * Creates an array containing the numeric code points of each Unicode
  	 * character in the string. While JavaScript uses UCS-2 internally,
  	 * this function will convert a pair of surrogate halves (each of which
  	 * UCS-2 exposes as separate characters) into a single code point,
  	 * matching UTF-16.
  	 * @see `punycode.ucs2.encode`
  	 * @see <https://mathiasbynens.be/notes/javascript-encoding>
  	 * @memberOf punycode.ucs2
  	 * @name decode
  	 * @param {String} string The Unicode input string (UCS-2).
  	 * @returns {Array} The new array of code points.
  	 */
  	function ucs2decode(string) {
  		var output = [],
  		    counter = 0,
  		    length = string.length,
  		    value,
  		    extra;
  		while (counter < length) {
  			value = string.charCodeAt(counter++);
  			if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
  				// high surrogate, and there is a next character
  				extra = string.charCodeAt(counter++);
  				if ((extra & 0xFC00) == 0xDC00) { // low surrogate
  					output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
  				} else {
  					// unmatched surrogate; only append this code unit, in case the next
  					// code unit is the high surrogate of a surrogate pair
  					output.push(value);
  					counter--;
  				}
  			} else {
  				output.push(value);
  			}
  		}
  		return output;
  	}
  
  	/**
  	 * Creates a string based on an array of numeric code points.
  	 * @see `punycode.ucs2.decode`
  	 * @memberOf punycode.ucs2
  	 * @name encode
  	 * @param {Array} codePoints The array of numeric code points.
  	 * @returns {String} The new Unicode string (UCS-2).
  	 */
  	function ucs2encode(array) {
  		return map(array, function(value) {
  			var output = '';
  			if (value > 0xFFFF) {
  				value -= 0x10000;
  				output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
  				value = 0xDC00 | value & 0x3FF;
  			}
  			output += stringFromCharCode(value);
  			return output;
  		}).join('');
  	}
  
  	/**
  	 * Converts a basic code point into a digit/integer.
  	 * @see `digitToBasic()`
  	 * @private
  	 * @param {Number} codePoint The basic numeric code point value.
  	 * @returns {Number} The numeric value of a basic code point (for use in
  	 * representing integers) in the range `0` to `base - 1`, or `base` if
  	 * the code point does not represent a value.
  	 */
  	function basicToDigit(codePoint) {
  		if (codePoint - 48 < 10) {
  			return codePoint - 22;
  		}
  		if (codePoint - 65 < 26) {
  			return codePoint - 65;
  		}
  		if (codePoint - 97 < 26) {
  			return codePoint - 97;
  		}
  		return base;
  	}
  
  	/**
  	 * Converts a digit/integer into a basic code point.
  	 * @see `basicToDigit()`
  	 * @private
  	 * @param {Number} digit The numeric value of a basic code point.
  	 * @returns {Number} The basic code point whose value (when used for
  	 * representing integers) is `digit`, which needs to be in the range
  	 * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
  	 * used; else, the lowercase form is used. The behavior is undefined
  	 * if `flag` is non-zero and `digit` has no uppercase form.
  	 */
  	function digitToBasic(digit, flag) {
  		//  0..25 map to ASCII a..z or A..Z
  		// 26..35 map to ASCII 0..9
  		return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
  	}
  
  	/**
  	 * Bias adaptation function as per section 3.4 of RFC 3492.
  	 * https://tools.ietf.org/html/rfc3492#section-3.4
  	 * @private
  	 */
  	function adapt(delta, numPoints, firstTime) {
  		var k = 0;
  		delta = firstTime ? floor(delta / damp) : delta >> 1;
  		delta += floor(delta / numPoints);
  		for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
  			delta = floor(delta / baseMinusTMin);
  		}
  		return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
  	}
  
  	/**
  	 * Converts a Punycode string of ASCII-only symbols to a string of Unicode
  	 * symbols.
  	 * @memberOf punycode
  	 * @param {String} input The Punycode string of ASCII-only symbols.
  	 * @returns {String} The resulting string of Unicode symbols.
  	 */
  	function decode(input) {
  		// Don't use UCS-2
  		var output = [],
  		    inputLength = input.length,
  		    out,
  		    i = 0,
  		    n = initialN,
  		    bias = initialBias,
  		    basic,
  		    j,
  		    index,
  		    oldi,
  		    w,
  		    k,
  		    digit,
  		    t,
  		    /** Cached calculation results */
  		    baseMinusT;
  
  		// Handle the basic code points: let `basic` be the number of input code
  		// points before the last delimiter, or `0` if there is none, then copy
  		// the first basic code points to the output.
  
  		basic = input.lastIndexOf(delimiter);
  		if (basic < 0) {
  			basic = 0;
  		}
  
  		for (j = 0; j < basic; ++j) {
  			// if it's not a basic code point
  			if (input.charCodeAt(j) >= 0x80) {
  				error('not-basic');
  			}
  			output.push(input.charCodeAt(j));
  		}
  
  		// Main decoding loop: start just after the last delimiter if any basic code
  		// points were copied; start at the beginning otherwise.
  
  		for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
  
  			// `index` is the index of the next character to be consumed.
  			// Decode a generalized variable-length integer into `delta`,
  			// which gets added to `i`. The overflow checking is easier
  			// if we increase `i` as we go, then subtract off its starting
  			// value at the end to obtain `delta`.
  			for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
  
  				if (index >= inputLength) {
  					error('invalid-input');
  				}
  
  				digit = basicToDigit(input.charCodeAt(index++));
  
  				if (digit >= base || digit > floor((maxInt - i) / w)) {
  					error('overflow');
  				}
  
  				i += digit * w;
  				t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
  
  				if (digit < t) {
  					break;
  				}
  
  				baseMinusT = base - t;
  				if (w > floor(maxInt / baseMinusT)) {
  					error('overflow');
  				}
  
  				w *= baseMinusT;
  
  			}
  
  			out = output.length + 1;
  			bias = adapt(i - oldi, out, oldi == 0);
  
  			// `i` was supposed to wrap around from `out` to `0`,
  			// incrementing `n` each time, so we'll fix that now:
  			if (floor(i / out) > maxInt - n) {
  				error('overflow');
  			}
  
  			n += floor(i / out);
  			i %= out;
  
  			// Insert `n` at position `i` of the output
  			output.splice(i++, 0, n);
  
  		}
  
  		return ucs2encode(output);
  	}
  
  	/**
  	 * Converts a string of Unicode symbols (e.g. a domain name label) to a
  	 * Punycode string of ASCII-only symbols.
  	 * @memberOf punycode
  	 * @param {String} input The string of Unicode symbols.
  	 * @returns {String} The resulting Punycode string of ASCII-only symbols.
  	 */
  	function encode(input) {
  		var n,
  		    delta,
  		    handledCPCount,
  		    basicLength,
  		    bias,
  		    j,
  		    m,
  		    q,
  		    k,
  		    t,
  		    currentValue,
  		    output = [],
  		    /** `inputLength` will hold the number of code points in `input`. */
  		    inputLength,
  		    /** Cached calculation results */
  		    handledCPCountPlusOne,
  		    baseMinusT,
  		    qMinusT;
  
  		// Convert the input in UCS-2 to Unicode
  		input = ucs2decode(input);
  
  		// Cache the length
  		inputLength = input.length;
  
  		// Initialize the state
  		n = initialN;
  		delta = 0;
  		bias = initialBias;
  
  		// Handle the basic code points
  		for (j = 0; j < inputLength; ++j) {
  			currentValue = input[j];
  			if (currentValue < 0x80) {
  				output.push(stringFromCharCode(currentValue));
  			}
  		}
  
  		handledCPCount = basicLength = output.length;
  
  		// `handledCPCount` is the number of code points that have been handled;
  		// `basicLength` is the number of basic code points.
  
  		// Finish the basic string - if it is not empty - with a delimiter
  		if (basicLength) {
  			output.push(delimiter);
  		}
  
  		// Main encoding loop:
  		while (handledCPCount < inputLength) {
  
  			// All non-basic code points < n have been handled already. Find the next
  			// larger one:
  			for (m = maxInt, j = 0; j < inputLength; ++j) {
  				currentValue = input[j];
  				if (currentValue >= n && currentValue < m) {
  					m = currentValue;
  				}
  			}
  
  			// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
  			// but guard against overflow
  			handledCPCountPlusOne = handledCPCount + 1;
  			if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
  				error('overflow');
  			}
  
  			delta += (m - n) * handledCPCountPlusOne;
  			n = m;
  
  			for (j = 0; j < inputLength; ++j) {
  				currentValue = input[j];
  
  				if (currentValue < n && ++delta > maxInt) {
  					error('overflow');
  				}
  
  				if (currentValue == n) {
  					// Represent delta as a generalized variable-length integer
  					for (q = delta, k = base; /* no condition */; k += base) {
  						t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
  						if (q < t) {
  							break;
  						}
  						qMinusT = q - t;
  						baseMinusT = base - t;
  						output.push(
  							stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
  						);
  						q = floor(qMinusT / baseMinusT);
  					}
  
  					output.push(stringFromCharCode(digitToBasic(q, 0)));
  					bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
  					delta = 0;
  					++handledCPCount;
  				}
  			}
  
  			++delta;
  			++n;
  
  		}
  		return output.join('');
  	}
  
  	/**
  	 * Converts a Punycode string representing a domain name or an email address
  	 * to Unicode. Only the Punycoded parts of the input will be converted, i.e.
  	 * it doesn't matter if you call it on a string that has already been
  	 * converted to Unicode.
  	 * @memberOf punycode
  	 * @param {String} input The Punycoded domain name or email address to
  	 * convert to Unicode.
  	 * @returns {String} The Unicode representation of the given Punycode
  	 * string.
  	 */
  	function toUnicode(input) {
  		return mapDomain(input, function(string) {
  			return regexPunycode.test(string)
  				? decode(string.slice(4).toLowerCase())
  				: string;
  		});
  	}
  
  	/**
  	 * Converts a Unicode string representing a domain name or an email address to
  	 * Punycode. Only the non-ASCII parts of the domain name will be converted,
  	 * i.e. it doesn't matter if you call it with a domain that's already in
  	 * ASCII.
  	 * @memberOf punycode
  	 * @param {String} input The domain name or email address to convert, as a
  	 * Unicode string.
  	 * @returns {String} The Punycode representation of the given domain name or
  	 * email address.
  	 */
  	function toASCII(input) {
  		return mapDomain(input, function(string) {
  			return regexNonASCII.test(string)
  				? 'xn--' + encode(string)
  				: string;
  		});
  	}
  
  	/*--------------------------------------------------------------------------*/
  
  	/** Define the public API */
  	punycode = {
  		/**
  		 * A string representing the current Punycode.js version number.
  		 * @memberOf punycode
  		 * @type String
  		 */
  		'version': '1.3.2',
  		/**
  		 * An object of methods to convert from JavaScript's internal character
  		 * representation (UCS-2) to Unicode code points, and back.
  		 * @see <https://mathiasbynens.be/notes/javascript-encoding>
  		 * @memberOf punycode
  		 * @type Object
  		 */
  		'ucs2': {
  			'decode': ucs2decode,
  			'encode': ucs2encode
  		},
  		'decode': decode,
  		'encode': encode,
  		'toASCII': toASCII,
  		'toUnicode': toUnicode
  	};
  
  	/** Expose `punycode` */
  	// Some AMD build optimizers, like r.js, check for specific condition patterns
  	// like the following:
  	if (
  		typeof define == 'function' &&
  		typeof define.amd == 'object' &&
  		define.amd
  	) {
  		define('punycode', function() {
  			return punycode;
  		});
  	} else if (freeExports && freeModule) {
  		if (module.exports == freeExports) {
  			// in Node.js, io.js, or RingoJS v0.8.0+
  			freeModule.exports = punycode;
  		} else {
  			// in Narwhal or RingoJS v0.7.0-
  			for (key in punycode) {
  				punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
  			}
  		}
  	} else {
  		// in Rhino or a web browser
  		root.punycode = punycode;
  	}
  
  }(this));
  
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{}],27:[function(require,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,
  // 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
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // 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.
  
  'use strict';
  
  // If obj.hasOwnProperty has been overridden, then calling
  // obj.hasOwnProperty(prop) will break.
  // See: https://github.com/joyent/node/issues/1707
  function hasOwnProperty(obj, prop) {
    return Object.prototype.hasOwnProperty.call(obj, prop);
  }
  
  module.exports = function(qs, sep, eq, options) {
    sep = sep || '&';
    eq = eq || '=';
    var obj = {};
  
    if (typeof qs !== 'string' || qs.length === 0) {
      return obj;
    }
  
    var regexp = /\+/g;
    qs = qs.split(sep);
  
    var maxKeys = 1000;
    if (options && typeof options.maxKeys === 'number') {
      maxKeys = options.maxKeys;
    }
  
    var len = qs.length;
    // maxKeys <= 0 means that we should not limit keys count
    if (maxKeys > 0 && len > maxKeys) {
      len = maxKeys;
    }
  
    for (var i = 0; i < len; ++i) {
      var x = qs[i].replace(regexp, '%20'),
          idx = x.indexOf(eq),
          kstr, vstr, k, v;
  
      if (idx >= 0) {
        kstr = x.substr(0, idx);
        vstr = x.substr(idx + 1);
      } else {
        kstr = x;
        vstr = '';
      }
  
      k = decodeURIComponent(kstr);
      v = decodeURIComponent(vstr);
  
      if (!hasOwnProperty(obj, k)) {
        obj[k] = v;
      } else if (isArray(obj[k])) {
        obj[k].push(v);
      } else {
        obj[k] = [obj[k], v];
      }
    }
  
    return obj;
  };
  
  var isArray = Array.isArray || function (xs) {
    return Object.prototype.toString.call(xs) === '[object Array]';
  };
  
  },{}],28:[function(require,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,
  // 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
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // 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.
  
  'use strict';
  
  var stringifyPrimitive = function(v) {
    switch (typeof v) {
      case 'string':
        return v;
  
      case 'boolean':
        return v ? 'true' : 'false';
  
      case 'number':
        return isFinite(v) ? v : '';
  
      default:
        return '';
    }
  };
  
  module.exports = function(obj, sep, eq, name) {
    sep = sep || '&';
    eq = eq || '=';
    if (obj === null) {
      obj = undefined;
    }
  
    if (typeof obj === 'object') {
      return map(objectKeys(obj), function(k) {
        var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;
        if (isArray(obj[k])) {
          return map(obj[k], function(v) {
            return ks + encodeURIComponent(stringifyPrimitive(v));
          }).join(sep);
        } else {
          return ks + encodeURIComponent(stringifyPrimitive(obj[k]));
        }
      }).join(sep);
  
    }
  
    if (!name) return '';
    return encodeURIComponent(stringifyPrimitive(name)) + eq +
           encodeURIComponent(stringifyPrimitive(obj));
  };
  
  var isArray = Array.isArray || function (xs) {
    return Object.prototype.toString.call(xs) === '[object Array]';
  };
  
  function map (xs, f) {
    if (xs.map) return xs.map(f);
    var res = [];
    for (var i = 0; i < xs.length; i++) {
      res.push(f(xs[i], i));
    }
    return res;
  }
  
  var objectKeys = Object.keys || function (obj) {
    var res = [];
    for (var key in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key);
    }
    return res;
  };
  
  },{}],29:[function(require,module,exports){
  'use strict';
  
  exports.decode = exports.parse = require('./decode');
  exports.encode = exports.stringify = require('./encode');
  
  },{"./decode":27,"./encode":28}],30:[function(require,module,exports){
  module.exports = require("./lib/_stream_duplex.js")
  
  },{"./lib/_stream_duplex.js":31}],31:[function(require,module,exports){
  // a duplex stream is just a stream that is both readable and writable.
  // Since JS doesn't have multiple prototypal inheritance, this class
  // prototypally inherits from Readable, and then parasitically from
  // Writable.
  
  'use strict';
  
  /*<replacement>*/
  var objectKeys = Object.keys || function (obj) {
    var keys = [];
    for (var key in obj) keys.push(key);
    return keys;
  }
  /*</replacement>*/
  
  
  module.exports = Duplex;
  
  /*<replacement>*/
  var processNextTick = require('process-nextick-args');
  /*</replacement>*/
  
  
  
  /*<replacement>*/
  var util = require('core-util-is');
  util.inherits = require('inherits');
  /*</replacement>*/
  
  var Readable = require('./_stream_readable');
  var Writable = require('./_stream_writable');
  
  util.inherits(Duplex, Readable);
  
  var keys = objectKeys(Writable.prototype);
  for (var v = 0; v < keys.length; v++) {
    var method = keys[v];
    if (!Duplex.prototype[method])
      Duplex.prototype[method] = Writable.prototype[method];
  }
  
  function Duplex(options) {
    if (!(this instanceof Duplex))
      return new Duplex(options);
  
    Readable.call(this, options);
    Writable.call(this, options);
  
    if (options && options.readable === false)
      this.readable = false;
  
    if (options && options.writable === false)
      this.writable = false;
  
    this.allowHalfOpen = true;
    if (options && options.allowHalfOpen === false)
      this.allowHalfOpen = false;
  
    this.once('end', onend);
  }
  
  // the no-half-open enforcer
  function onend() {
    // if we allow half-open state, or if the writable side ended,
    // then we're ok.
    if (this.allowHalfOpen || this._writableState.ended)
      return;
  
    // no more data can be written.
    // But allow more writes to happen in this tick.
    processNextTick(onEndNT, this);
  }
  
  function onEndNT(self) {
    self.end();
  }
  
  function forEach (xs, f) {
    for (var i = 0, l = xs.length; i < l; i++) {
      f(xs[i], i);
    }
  }
  
  },{"./_stream_readable":33,"./_stream_writable":35,"core-util-is":36,"inherits":21,"process-nextick-args":37}],32:[function(require,module,exports){
  // a passthrough stream.
  // basically just the most minimal sort of Transform stream.
  // Every written chunk gets output as-is.
  
  'use strict';
  
  module.exports = PassThrough;
  
  var Transform = require('./_stream_transform');
  
  /*<replacement>*/
  var util = require('core-util-is');
  util.inherits = require('inherits');
  /*</replacement>*/
  
  util.inherits(PassThrough, Transform);
  
  function PassThrough(options) {
    if (!(this instanceof PassThrough))
      return new PassThrough(options);
  
    Transform.call(this, options);
  }
  
  PassThrough.prototype._transform = function(chunk, encoding, cb) {
    cb(null, chunk);
  };
  
  },{"./_stream_transform":34,"core-util-is":36,"inherits":21}],33:[function(require,module,exports){
  (function (process){
  'use strict';
  
  module.exports = Readable;
  
  /*<replacement>*/
  var processNextTick = require('process-nextick-args');
  /*</replacement>*/
  
  
  /*<replacement>*/
  var isArray = require('isarray');
  /*</replacement>*/
  
  
  /*<replacement>*/
  var Buffer = require('buffer').Buffer;
  /*</replacement>*/
  
  Readable.ReadableState = ReadableState;
  
  var EE = require('events');
  
  /*<replacement>*/
  var EElistenerCount = function(emitter, type) {
    return emitter.listeners(type).length;
  };
  /*</replacement>*/
  
  
  
  /*<replacement>*/
  var Stream;
  (function (){try{
    Stream = require('st' + 'ream');
  }catch(_){}finally{
    if (!Stream)
      Stream = require('events').EventEmitter;
  }}())
  /*</replacement>*/
  
  var Buffer = require('buffer').Buffer;
  
  /*<replacement>*/
  var util = require('core-util-is');
  util.inherits = require('inherits');
  /*</replacement>*/
  
  
  
  /*<replacement>*/
  var debugUtil = require('util');
  var debug;
  if (debugUtil && debugUtil.debuglog) {
    debug = debugUtil.debuglog('stream');
  } else {
    debug = function () {};
  }
  /*</replacement>*/
  
  var StringDecoder;
  
  util.inherits(Readable, Stream);
  
  function ReadableState(options, stream) {
    var Duplex = require('./_stream_duplex');
  
    options = options || {};
  
    // object stream flag. Used to make read(n) ignore n and to
    // make all the buffer merging and length checks go away
    this.objectMode = !!options.objectMode;
  
    if (stream instanceof Duplex)
      this.objectMode = this.objectMode || !!options.readableObjectMode;
  
    // the point at which it stops calling _read() to fill the buffer
    // Note: 0 is a valid value, means "don't call _read preemptively ever"
    var hwm = options.highWaterMark;
    var defaultHwm = this.objectMode ? 16 : 16 * 1024;
    this.highWaterMark = (hwm || hwm === 0) ? hwm : defaultHwm;
  
    // cast to ints.
    this.highWaterMark = ~~this.highWaterMark;
  
    this.buffer = [];
    this.length = 0;
    this.pipes = null;
    this.pipesCount = 0;
    this.flowing = null;
    this.ended = false;
    this.endEmitted = false;
    this.reading = false;
  
    // a flag to be able to tell if the onwrite cb is called immediately,
    // or on a later tick.  We set this to true at first, because any
    // actions that shouldn't happen until "later" should generally also
    // not happen before the first write call.
    this.sync = true;
  
    // whenever we return null, then we set a flag to say
    // that we're awaiting a 'readable' event emission.
    this.needReadable = false;
    this.emittedReadable = false;
    this.readableListening = false;
  
    // Crypto is kind of old and crusty.  Historically, its default string
    // encoding is 'binary' so we have to make this configurable.
    // Everything else in the universe uses 'utf8', though.
    this.defaultEncoding = options.defaultEncoding || 'utf8';
  
    // when piping, we only care about 'readable' events that happen
    // after read()ing all the bytes and not getting any pushback.
    this.ranOut = false;
  
    // the number of writers that are awaiting a drain event in .pipe()s
    this.awaitDrain = 0;
  
    // if true, a maybeReadMore has been scheduled
    this.readingMore = false;
  
    this.decoder = null;
    this.encoding = null;
    if (options.encoding) {
      if (!StringDecoder)
        StringDecoder = require('string_decoder/').StringDecoder;
      this.decoder = new StringDecoder(options.encoding);
      this.encoding = options.encoding;
    }
  }
  
  function Readable(options) {
    var Duplex = require('./_stream_duplex');
  
    if (!(this instanceof Readable))
      return new Readable(options);
  
    this._readableState = new ReadableState(options, this);
  
    // legacy
    this.readable = true;
  
    if (options && typeof options.read === 'function')
      this._read = options.read;
  
    Stream.call(this);
  }
  
  // Manually shove something into the read() buffer.
  // This returns true if the highWaterMark has not been hit yet,
  // similar to how Writable.write() returns true if you should
  // write() some more.
  Readable.prototype.push = function(chunk, encoding) {
    var state = this._readableState;
  
    if (!state.objectMode && typeof chunk === 'string') {
      encoding = encoding || state.defaultEncoding;
      if (encoding !== state.encoding) {
        chunk = new Buffer(chunk, encoding);
        encoding = '';
      }
    }
  
    return readableAddChunk(this, state, chunk, encoding, false);
  };
  
  // Unshift should *always* be something directly out of read()
  Readable.prototype.unshift = function(chunk) {
    var state = this._readableState;
    return readableAddChunk(this, state, chunk, '', true);
  };
  
  Readable.prototype.isPaused = function() {
    return this._readableState.flowing === false;
  };
  
  function readableAddChunk(stream, state, chunk, encoding, addToFront) {
    var er = chunkInvalid(state, chunk);
    if (er) {
      stream.emit('error', er);
    } else if (chunk === null) {
      state.reading = false;
      onEofChunk(stream, state);
    } else if (state.objectMode || chunk && chunk.length > 0) {
      if (state.ended && !addToFront) {
        var e = new Error('stream.push() after EOF');
        stream.emit('error', e);
      } else if (state.endEmitted && addToFront) {
        var e = new Error('stream.unshift() after end event');
        stream.emit('error', e);
      } else {
        if (state.decoder && !addToFront && !encoding)
          chunk = state.decoder.write(chunk);
  
        if (!addToFront)
          state.reading = false;
  
        // if we want the data now, just emit it.
        if (state.flowing && state.length === 0 && !state.sync) {
          stream.emit('data', chunk);
          stream.read(0);
        } else {
          // update the buffer info.
          state.length += state.objectMode ? 1 : chunk.length;
          if (addToFront)
            state.buffer.unshift(chunk);
          else
            state.buffer.push(chunk);
  
          if (state.needReadable)
            emitReadable(stream);
        }
  
        maybeReadMore(stream, state);
      }
    } else if (!addToFront) {
      state.reading = false;
    }
  
    return needMoreData(state);
  }
  
  
  // if it's past the high water mark, we can push in some more.
  // Also, if we have no data yet, we can stand some
  // more bytes.  This is to work around cases where hwm=0,
  // such as the repl.  Also, if the push() triggered a
  // readable event, and the user called read(largeNumber) such that
  // needReadable was set, then we ought to push more, so that another
  // 'readable' event will be triggered.
  function needMoreData(state) {
    return !state.ended &&
           (state.needReadable ||
            state.length < state.highWaterMark ||
            state.length === 0);
  }
  
  // backwards compatibility.
  Readable.prototype.setEncoding = function(enc) {
    if (!StringDecoder)
      StringDecoder = require('string_decoder/').StringDecoder;
    this._readableState.decoder = new StringDecoder(enc);
    this._readableState.encoding = enc;
    return this;
  };
  
  // Don't raise the hwm > 8MB
  var MAX_HWM = 0x800000;
  function computeNewHighWaterMark(n) {
    if (n >= MAX_HWM) {
      n = MAX_HWM;
    } else {
      // Get the next highest power of 2
      n--;
      n |= n >>> 1;
      n |= n >>> 2;
      n |= n >>> 4;
      n |= n >>> 8;
      n |= n >>> 16;
      n++;
    }
    return n;
  }
  
  function howMuchToRead(n, state) {
    if (state.length === 0 && state.ended)
      return 0;
  
    if (state.objectMode)
      return n === 0 ? 0 : 1;
  
    if (n === null || isNaN(n)) {
      // only flow one buffer at a time
      if (state.flowing && state.buffer.length)
        return state.buffer[0].length;
      else
        return state.length;
    }
  
    if (n <= 0)
      return 0;
  
    // If we're asking for more than the target buffer level,
    // then raise the water mark.  Bump up to the next highest
    // power of 2, to prevent increasing it excessively in tiny
    // amounts.
    if (n > state.highWaterMark)
      state.highWaterMark = computeNewHighWaterMark(n);
  
    // don't have that much.  return null, unless we've ended.
    if (n > state.length) {
      if (!state.ended) {
        state.needReadable = true;
        return 0;
      } else {
        return state.length;
      }
    }
  
    return n;
  }
  
  // you can override either this method, or the async _read(n) below.
  Readable.prototype.read = function(n) {
    debug('read', n);
    var state = this._readableState;
    var nOrig = n;
  
    if (typeof n !== 'number' || n > 0)
      state.emittedReadable = false;
  
    // if we're doing read(0) to trigger a readable event, but we
    // already have a bunch of data in the buffer, then just trigger
    // the 'readable' event and move on.
    if (n === 0 &&
        state.needReadable &&
        (state.length >= state.highWaterMark || state.ended)) {
      debug('read: emitReadable', state.length, state.ended);
      if (state.length === 0 && state.ended)
        endReadable(this);
      else
        emitReadable(this);
      return null;
    }
  
    n = howMuchToRead(n, state);
  
    // if we've ended, and we're now clear, then finish it up.
    if (n === 0 && state.ended) {
      if (state.length === 0)
        endReadable(this);
      return null;
    }
  
    // All the actual chunk generation logic needs to be
    // *below* the call to _read.  The reason is that in certain
    // synthetic stream cases, such as passthrough streams, _read
    // may be a completely synchronous operation which may change
    // the state of the read buffer, providing enough data when
    // before there was *not* enough.
    //
    // So, the steps are:
    // 1. Figure out what the state of things will be after we do
    // a read from the buffer.
    //
    // 2. If that resulting state will trigger a _read, then call _read.
    // Note that this may be asynchronous, or synchronous.  Yes, it is
    // deeply ugly to write APIs this way, but that still doesn't mean
    // that the Readable class should behave improperly, as streams are
    // designed to be sync/async agnostic.
    // Take note if the _read call is sync or async (ie, if the read call
    // has returned yet), so that we know whether or not it's safe to emit
    // 'readable' etc.
    //
    // 3. Actually pull the requested chunks out of the buffer and return.
  
    // if we need a readable event, then we need to do some reading.
    var doRead = state.needReadable;
    debug('need readable', doRead);
  
    // if we currently have less than the highWaterMark, then also read some
    if (state.length === 0 || state.length - n < state.highWaterMark) {
      doRead = true;
      debug('length less than watermark', doRead);
    }
  
    // however, if we've ended, then there's no point, and if we're already
    // reading, then it's unnecessary.
    if (state.ended || state.reading) {
      doRead = false;
      debug('reading or ended', doRead);
    }
  
    if (doRead) {
      debug('do read');
      state.reading = true;
      state.sync = true;
      // if the length is currently zero, then we *need* a readable event.
      if (state.length === 0)
        state.needReadable = true;
      // call internal read method
      this._read(state.highWaterMark);
      state.sync = false;
    }
  
    // If _read pushed data synchronously, then `reading` will be false,
    // and we need to re-evaluate how much data we can return to the user.
    if (doRead && !state.reading)
      n = howMuchToRead(nOrig, state);
  
    var ret;
    if (n > 0)
      ret = fromList(n, state);
    else
      ret = null;
  
    if (ret === null) {
      state.needReadable = true;
      n = 0;
    }
  
    state.length -= n;
  
    // If we have nothing in the buffer, then we want to know
    // as soon as we *do* get something into the buffer.
    if (state.length === 0 && !state.ended)
      state.needReadable = true;
  
    // If we tried to read() past the EOF, then emit end on the next tick.
    if (nOrig !== n && state.ended && state.length === 0)
      endReadable(this);
  
    if (ret !== null)
      this.emit('data', ret);
  
    return ret;
  };
  
  function chunkInvalid(state, chunk) {
    var er = null;
    if (!(Buffer.isBuffer(chunk)) &&
        typeof chunk !== 'string' &&
        chunk !== null &&
        chunk !== undefined &&
        !state.objectMode) {
      er = new TypeError('Invalid non-string/buffer chunk');
    }
    return er;
  }
  
  
  function onEofChunk(stream, state) {
    if (state.ended) return;
    if (state.decoder) {
      var chunk = state.decoder.end();
      if (chunk && chunk.length) {
        state.buffer.push(chunk);
        state.length += state.objectMode ? 1 : chunk.length;
      }
    }
    state.ended = true;
  
    // emit 'readable' now to make sure it gets picked up.
    emitReadable(stream);
  }
  
  // Don't emit readable right away in sync mode, because this can trigger
  // another read() call => stack overflow.  This way, it might trigger
  // a nextTick recursion warning, but that's not so bad.
  function emitReadable(stream) {
    var state = stream._readableState;
    state.needReadable = false;
    if (!state.emittedReadable) {
      debug('emitReadable', state.flowing);
      state.emittedReadable = true;
      if (state.sync)
        processNextTick(emitReadable_, stream);
      else
        emitReadable_(stream);
    }
  }
  
  function emitReadable_(stream) {
    debug('emit readable');
    stream.emit('readable');
    flow(stream);
  }
  
  
  // at this point, the user has presumably seen the 'readable' event,
  // and called read() to consume some data.  that may have triggered
  // in turn another _read(n) call, in which case reading = true if
  // it's in progress.
  // However, if we're not ended, or reading, and the length < hwm,
  // then go ahead and try to read some more preemptively.
  function maybeReadMore(stream, state) {
    if (!state.readingMore) {
      state.readingMore = true;
      processNextTick(maybeReadMore_, stream, state);
    }
  }
  
  function maybeReadMore_(stream, state) {
    var len = state.length;
    while (!state.reading && !state.flowing && !state.ended &&
           state.length < state.highWaterMark) {
      debug('maybeReadMore read 0');
      stream.read(0);
      if (len === state.length)
        // didn't get any data, stop spinning.
        break;
      else
        len = state.length;
    }
    state.readingMore = false;
  }
  
  // abstract method.  to be overridden in specific implementation classes.
  // call cb(er, data) where data is <= n in length.
  // for virtual (non-string, non-buffer) streams, "length" is somewhat
  // arbitrary, and perhaps not very meaningful.
  Readable.prototype._read = function(n) {
    this.emit('error', new Error('not implemented'));
  };
  
  Readable.prototype.pipe = function(dest, pipeOpts) {
    var src = this;
    var state = this._readableState;
  
    switch (state.pipesCount) {
      case 0:
        state.pipes = dest;
        break;
      case 1:
        state.pipes = [state.pipes, dest];
        break;
      default:
        state.pipes.push(dest);
        break;
    }
    state.pipesCount += 1;
    debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts);
  
    var doEnd = (!pipeOpts || pipeOpts.end !== false) &&
                dest !== process.stdout &&
                dest !== process.stderr;
  
    var endFn = doEnd ? onend : cleanup;
    if (state.endEmitted)
      processNextTick(endFn);
    else
      src.once('end', endFn);
  
    dest.on('unpipe', onunpipe);
    function onunpipe(readable) {
      debug('onunpipe');
      if (readable === src) {
        cleanup();
      }
    }
  
    function onend() {
      debug('onend');
      dest.end();
    }
  
    // when the dest drains, it reduces the awaitDrain counter
    // on the source.  This would be more elegant with a .once()
    // handler in flow(), but adding and removing repeatedly is
    // too slow.
    var ondrain = pipeOnDrain(src);
    dest.on('drain', ondrain);
  
    var cleanedUp = false;
    function cleanup() {
      debug('cleanup');
      // cleanup event handlers once the pipe is broken
      dest.removeListener('close', onclose);
      dest.removeListener('finish', onfinish);
      dest.removeListener('drain', ondrain);
      dest.removeListener('error', onerror);
      dest.removeListener('unpipe', onunpipe);
      src.removeListener('end', onend);
      src.removeListener('end', cleanup);
      src.removeListener('data', ondata);
  
      cleanedUp = true;
  
      // if the reader is waiting for a drain event from this
      // specific writer, then it would cause it to never start
      // flowing again.
      // So, if this is awaiting a drain, then we just call it now.
      // If we don't know, then assume that we are waiting for one.
      if (state.awaitDrain &&
          (!dest._writableState || dest._writableState.needDrain))
        ondrain();
    }
  
    src.on('data', ondata);
    function ondata(chunk) {
      debug('ondata');
      var ret = dest.write(chunk);
      if (false === ret) {
        // If the user unpiped during `dest.write()`, it is possible
        // to get stuck in a permanently paused state if that write
        // also returned false.
        if (state.pipesCount === 1 &&
            state.pipes[0] === dest &&
            src.listenerCount('data') === 1 &&
            !cleanedUp) {
          debug('false write response, pause', src._readableState.awaitDrain);
          src._readableState.awaitDrain++;
        }
        src.pause();
      }
    }
  
    // if the dest has an error, then stop piping into it.
    // however, don't suppress the throwing behavior for this.
    function onerror(er) {
      debug('onerror', er);
      unpipe();
      dest.removeListener('error', onerror);
      if (EElistenerCount(dest, 'error') === 0)
        dest.emit('error', er);
    }
    // This is a brutally ugly hack to make sure that our error handler
    // is attached before any userland ones.  NEVER DO THIS.
    if (!dest._events || !dest._events.error)
      dest.on('error', onerror);
    else if (isArray(dest._events.error))
      dest._events.error.unshift(onerror);
    else
      dest._events.error = [onerror, dest._events.error];
  
  
    // Both close and finish should trigger unpipe, but only once.
    function onclose() {
      dest.removeListener('finish', onfinish);
      unpipe();
    }
    dest.once('close', onclose);
    function onfinish() {
      debug('onfinish');
      dest.removeListener('close', onclose);
      unpipe();
    }
    dest.once('finish', onfinish);
  
    function unpipe() {
      debug('unpipe');
      src.unpipe(dest);
    }
  
    // tell the dest that it's being piped to
    dest.emit('pipe', src);
  
    // start the flow if it hasn't been started already.
    if (!state.flowing) {
      debug('pipe resume');
      src.resume();
    }
  
    return dest;
  };
  
  function pipeOnDrain(src) {
    return function() {
      var state = src._readableState;
      debug('pipeOnDrain', state.awaitDrain);
      if (state.awaitDrain)
        state.awaitDrain--;
      if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) {
        state.flowing = true;
        flow(src);
      }
    };
  }
  
  
  Readable.prototype.unpipe = function(dest) {
    var state = this._readableState;
  
    // if we're not piping anywhere, then do nothing.
    if (state.pipesCount === 0)
      return this;
  
    // just one destination.  most common case.
    if (state.pipesCount === 1) {
      // passed in one, but it's not the right one.
      if (dest && dest !== state.pipes)
        return this;
  
      if (!dest)
        dest = state.pipes;
  
      // got a match.
      state.pipes = null;
      state.pipesCount = 0;
      state.flowing = false;
      if (dest)
        dest.emit('unpipe', this);
      return this;
    }
  
    // slow case. multiple pipe destinations.
  
    if (!dest) {
      // remove all.
      var dests = state.pipes;
      var len = state.pipesCount;
      state.pipes = null;
      state.pipesCount = 0;
      state.flowing = false;
  
      for (var i = 0; i < len; i++)
        dests[i].emit('unpipe', this);
      return this;
    }
  
    // try to find the right one.
    var i = indexOf(state.pipes, dest);
    if (i === -1)
      return this;
  
    state.pipes.splice(i, 1);
    state.pipesCount -= 1;
    if (state.pipesCount === 1)
      state.pipes = state.pipes[0];
  
    dest.emit('unpipe', this);
  
    return this;
  };
  
  // set up data events if they are asked for
  // Ensure readable listeners eventually get something
  Readable.prototype.on = function(ev, fn) {
    var res = Stream.prototype.on.call(this, ev, fn);
  
    // If listening to data, and it has not explicitly been paused,
    // then call resume to start the flow of data on the next tick.
    if (ev === 'data' && false !== this._readableState.flowing) {
      this.resume();
    }
  
    if (ev === 'readable' && this.readable) {
      var state = this._readableState;
      if (!state.readableListening) {
        state.readableListening = true;
        state.emittedReadable = false;
        state.needReadable = true;
        if (!state.reading) {
          processNextTick(nReadingNextTick, this);
        } else if (state.length) {
          emitReadable(this, state);
        }
      }
    }
  
    return res;
  };
  Readable.prototype.addListener = Readable.prototype.on;
  
  function nReadingNextTick(self) {
    debug('readable nexttick read 0');
    self.read(0);
  }
  
  // pause() and resume() are remnants of the legacy readable stream API
  // If the user uses them, then switch into old mode.
  Readable.prototype.resume = function() {
    var state = this._readableState;
    if (!state.flowing) {
      debug('resume');
      state.flowing = true;
      resume(this, state);
    }
    return this;
  };
  
  function resume(stream, state) {
    if (!state.resumeScheduled) {
      state.resumeScheduled = true;
      processNextTick(resume_, stream, state);
    }
  }
  
  function resume_(stream, state) {
    if (!state.reading) {
      debug('resume read 0');
      stream.read(0);
    }
  
    state.resumeScheduled = false;
    stream.emit('resume');
    flow(stream);
    if (state.flowing && !state.reading)
      stream.read(0);
  }
  
  Readable.prototype.pause = function() {
    debug('call pause flowing=%j', this._readableState.flowing);
    if (false !== this._readableState.flowing) {
      debug('pause');
      this._readableState.flowing = false;
      this.emit('pause');
    }
    return this;
  };
  
  function flow(stream) {
    var state = stream._readableState;
    debug('flow', state.flowing);
    if (state.flowing) {
      do {
        var chunk = stream.read();
      } while (null !== chunk && state.flowing);
    }
  }
  
  // wrap an old-style stream as the async data source.
  // This is *not* part of the readable stream interface.
  // It is an ugly unfortunate mess of history.
  Readable.prototype.wrap = function(stream) {
    var state = this._readableState;
    var paused = false;
  
    var self = this;
    stream.on('end', function() {
      debug('wrapped end');
      if (state.decoder && !state.ended) {
        var chunk = state.decoder.end();
        if (chunk && chunk.length)
          self.push(chunk);
      }
  
      self.push(null);
    });
  
    stream.on('data', function(chunk) {
      debug('wrapped data');
      if (state.decoder)
        chunk = state.decoder.write(chunk);
  
      // don't skip over falsy values in objectMode
      if (state.objectMode && (chunk === null || chunk === undefined))
        return;
      else if (!state.objectMode && (!chunk || !chunk.length))
        return;
  
      var ret = self.push(chunk);
      if (!ret) {
        paused = true;
        stream.pause();
      }
    });
  
    // proxy all the other methods.
    // important when wrapping filters and duplexes.
    for (var i in stream) {
      if (this[i] === undefined && typeof stream[i] === 'function') {
        this[i] = function(method) { return function() {
          return stream[method].apply(stream, arguments);
        }; }(i);
      }
    }
  
    // proxy certain important events.
    var events = ['error', 'close', 'destroy', 'pause', 'resume'];
    forEach(events, function(ev) {
      stream.on(ev, self.emit.bind(self, ev));
    });
  
    // when we try to consume some more bytes, simply unpause the
    // underlying stream.
    self._read = function(n) {
      debug('wrapped _read', n);
      if (paused) {
        paused = false;
        stream.resume();
      }
    };
  
    return self;
  };
  
  
  // exposed for testing purposes only.
  Readable._fromList = fromList;
  
  // Pluck off n bytes from an array of buffers.
  // Length is the combined lengths of all the buffers in the list.
  function fromList(n, state) {
    var list = state.buffer;
    var length = state.length;
    var stringMode = !!state.decoder;
    var objectMode = !!state.objectMode;
    var ret;
  
    // nothing in the list, definitely empty.
    if (list.length === 0)
      return null;
  
    if (length === 0)
      ret = null;
    else if (objectMode)
      ret = list.shift();
    else if (!n || n >= length) {
      // read it all, truncate the array.
      if (stringMode)
        ret = list.join('');
      else if (list.length === 1)
        ret = list[0];
      else
        ret = Buffer.concat(list, length);
      list.length = 0;
    } else {
      // read just some of it.
      if (n < list[0].length) {
        // just take a part of the first list item.
        // slice is the same for buffers and strings.
        var buf = list[0];
        ret = buf.slice(0, n);
        list[0] = buf.slice(n);
      } else if (n === list[0].length) {
        // first list is a perfect match
        ret = list.shift();
      } else {
        // complex case.
        // we have enough to cover it, but it spans past the first buffer.
        if (stringMode)
          ret = '';
        else
          ret = new Buffer(n);
  
        var c = 0;
        for (var i = 0, l = list.length; i < l && c < n; i++) {
          var buf = list[0];
          var cpy = Math.min(n - c, buf.length);
  
          if (stringMode)
            ret += buf.slice(0, cpy);
          else
            buf.copy(ret, c, 0, cpy);
  
          if (cpy < buf.length)
            list[0] = buf.slice(cpy);
          else
            list.shift();
  
          c += cpy;
        }
      }
    }
  
    return ret;
  }
  
  function endReadable(stream) {
    var state = stream._readableState;
  
    // If we get here before consuming all the bytes, then that is a
    // bug in node.  Should never happen.
    if (state.length > 0)
      throw new Error('endReadable called on non-empty stream');
  
    if (!state.endEmitted) {
      state.ended = true;
      processNextTick(endReadableNT, state, stream);
    }
  }
  
  function endReadableNT(state, stream) {
    // Check that we didn't get one last unshift.
    if (!state.endEmitted && state.length === 0) {
      state.endEmitted = true;
      stream.readable = false;
      stream.emit('end');
    }
  }
  
  function forEach (xs, f) {
    for (var i = 0, l = xs.length; i < l; i++) {
      f(xs[i], i);
    }
  }
  
  function indexOf (xs, x) {
    for (var i = 0, l = xs.length; i < l; i++) {
      if (xs[i] === x) return i;
    }
    return -1;
  }
  
  }).call(this,require('_process'))
  },{"./_stream_duplex":31,"_process":25,"buffer":15,"core-util-is":36,"events":19,"inherits":21,"isarray":23,"process-nextick-args":37,"string_decoder/":49,"util":14}],34:[function(require,module,exports){
  // a transform stream is a readable/writable stream where you do
  // something with the data.  Sometimes it's called a "filter",
  // but that's not a great name for it, since that implies a thing where
  // some bits pass through, and others are simply ignored.  (That would
  // be a valid example of a transform, of course.)
  //
  // While the output is causally related to the input, it's not a
  // necessarily symmetric or synchronous transformation.  For example,
  // a zlib stream might take multiple plain-text writes(), and then
  // emit a single compressed chunk some time in the future.
  //
  // Here's how this works:
  //
  // The Transform stream has all the aspects of the readable and writable
  // stream classes.  When you write(chunk), that calls _write(chunk,cb)
  // internally, and returns false if there's a lot of pending writes
  // buffered up.  When you call read(), that calls _read(n) until
  // there's enough pending readable data buffered up.
  //
  // In a transform stream, the written data is placed in a buffer.  When
  // _read(n) is called, it transforms the queued up data, calling the
  // buffered _write cb's as it consumes chunks.  If consuming a single
  // written chunk would result in multiple output chunks, then the first
  // outputted bit calls the readcb, and subsequent chunks just go into
  // the read buffer, and will cause it to emit 'readable' if necessary.
  //
  // This way, back-pressure is actually determined by the reading side,
  // since _read has to be called to start processing a new chunk.  However,
  // a pathological inflate type of transform can cause excessive buffering
  // here.  For example, imagine a stream where every byte of input is
  // interpreted as an integer from 0-255, and then results in that many
  // bytes of output.  Writing the 4 bytes {ff,ff,ff,ff} would result in
  // 1kb of data being output.  In this case, you could write a very small
  // amount of input, and end up with a very large amount of output.  In
  // such a pathological inflating mechanism, there'd be no way to tell
  // the system to stop doing the transform.  A single 4MB write could
  // cause the system to run out of memory.
  //
  // However, even in such a pathological case, only a single written chunk
  // would be consumed, and then the rest would wait (un-transformed) until
  // the results of the previous transformed chunk were consumed.
  
  'use strict';
  
  module.exports = Transform;
  
  var Duplex = require('./_stream_duplex');
  
  /*<replacement>*/
  var util = require('core-util-is');
  util.inherits = require('inherits');
  /*</replacement>*/
  
  util.inherits(Transform, Duplex);
  
  
  function TransformState(stream) {
    this.afterTransform = function(er, data) {
      return afterTransform(stream, er, data);
    };
  
    this.needTransform = false;
    this.transforming = false;
    this.writecb = null;
    this.writechunk = null;
  }
  
  function afterTransform(stream, er, data) {
    var ts = stream._transformState;
    ts.transforming = false;
  
    var cb = ts.writecb;
  
    if (!cb)
      return stream.emit('error', new Error('no writecb in Transform class'));
  
    ts.writechunk = null;
    ts.writecb = null;
  
    if (data !== null && data !== undefined)
      stream.push(data);
  
    if (cb)
      cb(er);
  
    var rs = stream._readableState;
    rs.reading = false;
    if (rs.needReadable || rs.length < rs.highWaterMark) {
      stream._read(rs.highWaterMark);
    }
  }
  
  
  function Transform(options) {
    if (!(this instanceof Transform))
      return new Transform(options);
  
    Duplex.call(this, options);
  
    this._transformState = new TransformState(this);
  
    // when the writable side finishes, then flush out anything remaining.
    var stream = this;
  
    // start out asking for a readable event once data is transformed.
    this._readableState.needReadable = true;
  
    // we have implemented the _read method, and done the other things
    // that Readable wants before the first _read call, so unset the
    // sync guard flag.
    this._readableState.sync = false;
  
    if (options) {
      if (typeof options.transform === 'function')
        this._transform = options.transform;
  
      if (typeof options.flush === 'function')
        this._flush = options.flush;
    }
  
    this.once('prefinish', function() {
      if (typeof this._flush === 'function')
        this._flush(function(er) {
          done(stream, er);
        });
      else
        done(stream);
    });
  }
  
  Transform.prototype.push = function(chunk, encoding) {
    this._transformState.needTransform = false;
    return Duplex.prototype.push.call(this, chunk, encoding);
  };
  
  // This is the part where you do stuff!
  // override this function in implementation classes.
  // 'chunk' is an input chunk.
  //
  // Call `push(newChunk)` to pass along transformed output
  // to the readable side.  You may call 'push' zero or more times.
  //
  // Call `cb(err)` when you are done with this chunk.  If you pass
  // an error, then that'll put the hurt on the whole operation.  If you
  // never call cb(), then you'll never get another chunk.
  Transform.prototype._transform = function(chunk, encoding, cb) {
    throw new Error('not implemented');
  };
  
  Transform.prototype._write = function(chunk, encoding, cb) {
    var ts = this._transformState;
    ts.writecb = cb;
    ts.writechunk = chunk;
    ts.writeencoding = encoding;
    if (!ts.transforming) {
      var rs = this._readableState;
      if (ts.needTransform ||
          rs.needReadable ||
          rs.length < rs.highWaterMark)
        this._read(rs.highWaterMark);
    }
  };
  
  // Doesn't matter what the args are here.
  // _transform does all the work.
  // That we got here means that the readable side wants more data.
  Transform.prototype._read = function(n) {
    var ts = this._transformState;
  
    if (ts.writechunk !== null && ts.writecb && !ts.transforming) {
      ts.transforming = true;
      this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform);
    } else {
      // mark that we need a transform, so that any data that comes in
      // will get processed, now that we've asked for it.
      ts.needTransform = true;
    }
  };
  
  
  function done(stream, er) {
    if (er)
      return stream.emit('error', er);
  
    // if there's nothing in the write buffer, then that means
    // that nothing more will ever be provided
    var ws = stream._writableState;
    var ts = stream._transformState;
  
    if (ws.length)
      throw new Error('calling transform done when ws.length != 0');
  
    if (ts.transforming)
      throw new Error('calling transform done when still transforming');
  
    return stream.push(null);
  }
  
  },{"./_stream_duplex":31,"core-util-is":36,"inherits":21}],35:[function(require,module,exports){
  // A bit simpler than readable streams.
  // Implement an async ._write(chunk, encoding, cb), and it'll handle all
  // the drain event emission and buffering.
  
  'use strict';
  
  module.exports = Writable;
  
  /*<replacement>*/
  var processNextTick = require('process-nextick-args');
  /*</replacement>*/
  
  
  /*<replacement>*/
  var Buffer = require('buffer').Buffer;
  /*</replacement>*/
  
  Writable.WritableState = WritableState;
  
  
  /*<replacement>*/
  var util = require('core-util-is');
  util.inherits = require('inherits');
  /*</replacement>*/
  
  
  /*<replacement>*/
  var internalUtil = {
    deprecate: require('util-deprecate')
  };
  /*</replacement>*/
  
  
  
  /*<replacement>*/
  var Stream;
  (function (){try{
    Stream = require('st' + 'ream');
  }catch(_){}finally{
    if (!Stream)
      Stream = require('events').EventEmitter;
  }}())
  /*</replacement>*/
  
  var Buffer = require('buffer').Buffer;
  
  util.inherits(Writable, Stream);
  
  function nop() {}
  
  function WriteReq(chunk, encoding, cb) {
    this.chunk = chunk;
    this.encoding = encoding;
    this.callback = cb;
    this.next = null;
  }
  
  function WritableState(options, stream) {
    var Duplex = require('./_stream_duplex');
  
    options = options || {};
  
    // object stream flag to indicate whether or not this stream
    // contains buffers or objects.
    this.objectMode = !!options.objectMode;
  
    if (stream instanceof Duplex)
      this.objectMode = this.objectMode || !!options.writableObjectMode;
  
    // the point at which write() starts returning false
    // Note: 0 is a valid value, means that we always return false if
    // the entire buffer is not flushed immediately on write()
    var hwm = options.highWaterMark;
    var defaultHwm = this.objectMode ? 16 : 16 * 1024;
    this.highWaterMark = (hwm || hwm === 0) ? hwm : defaultHwm;
  
    // cast to ints.
    this.highWaterMark = ~~this.highWaterMark;
  
    this.needDrain = false;
    // at the start of calling end()
    this.ending = false;
    // when end() has been called, and returned
    this.ended = false;
    // when 'finish' is emitted
    this.finished = false;
  
    // should we decode strings into buffers before passing to _write?
    // this is here so that some node-core streams can optimize string
    // handling at a lower level.
    var noDecode = options.decodeStrings === false;
    this.decodeStrings = !noDecode;
  
    // Crypto is kind of old and crusty.  Historically, its default string
    // encoding is 'binary' so we have to make this configurable.
    // Everything else in the universe uses 'utf8', though.
    this.defaultEncoding = options.defaultEncoding || 'utf8';
  
    // not an actual buffer we keep track of, but a measurement
    // of how much we're waiting to get pushed to some underlying
    // socket or file.
    this.length = 0;
  
    // a flag to see when we're in the middle of a write.
    this.writing = false;
  
    // when true all writes will be buffered until .uncork() call
    this.corked = 0;
  
    // a flag to be able to tell if the onwrite cb is called immediately,
    // or on a later tick.  We set this to true at first, because any
    // actions that shouldn't happen until "later" should generally also
    // not happen before the first write call.
    this.sync = true;
  
    // a flag to know if we're processing previously buffered items, which
    // may call the _write() callback in the same tick, so that we don't
    // end up in an overlapped onwrite situation.
    this.bufferProcessing = false;
  
    // the callback that's passed to _write(chunk,cb)
    this.onwrite = function(er) {
      onwrite(stream, er);
    };
  
    // the callback that the user supplies to write(chunk,encoding,cb)
    this.writecb = null;
  
    // the amount that is being written when _write is called.
    this.writelen = 0;
  
    this.bufferedRequest = null;
    this.lastBufferedRequest = null;
  
    // number of pending user-supplied write callbacks
    // this must be 0 before 'finish' can be emitted
    this.pendingcb = 0;
  
    // emit prefinish if the only thing we're waiting for is _write cbs
    // This is relevant for synchronous Transform streams
    this.prefinished = false;
  
    // True if the error was already emitted and should not be thrown again
    this.errorEmitted = false;
  }
  
  WritableState.prototype.getBuffer = function writableStateGetBuffer() {
    var current = this.bufferedRequest;
    var out = [];
    while (current) {
      out.push(current);
      current = current.next;
    }
    return out;
  };
  
  (function (){try {
  Object.defineProperty(WritableState.prototype, 'buffer', {
    get: internalUtil.deprecate(function() {
      return this.getBuffer();
    }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' +
       'instead.')
  });
  }catch(_){}}());
  
  
  function Writable(options) {
    var Duplex = require('./_stream_duplex');
  
    // Writable ctor is applied to Duplexes, though they're not
    // instanceof Writable, they're instanceof Readable.
    if (!(this instanceof Writable) && !(this instanceof Duplex))
      return new Writable(options);
  
    this._writableState = new WritableState(options, this);
  
    // legacy.
    this.writable = true;
  
    if (options) {
      if (typeof options.write === 'function')
        this._write = options.write;
  
      if (typeof options.writev === 'function')
        this._writev = options.writev;
    }
  
    Stream.call(this);
  }
  
  // Otherwise people can pipe Writable streams, which is just wrong.
  Writable.prototype.pipe = function() {
    this.emit('error', new Error('Cannot pipe. Not readable.'));
  };
  
  
  function writeAfterEnd(stream, cb) {
    var er = new Error('write after end');
    // TODO: defer error events consistently everywhere, not just the cb
    stream.emit('error', er);
    processNextTick(cb, er);
  }
  
  // If we get something that is not a buffer, string, null, or undefined,
  // and we're not in objectMode, then that's an error.
  // Otherwise stream chunks are all considered to be of length=1, and the
  // watermarks determine how many objects to keep in the buffer, rather than
  // how many bytes or characters.
  function validChunk(stream, state, chunk, cb) {
    var valid = true;
  
    if (!(Buffer.isBuffer(chunk)) &&
        typeof chunk !== 'string' &&
        chunk !== null &&
        chunk !== undefined &&
        !state.objectMode) {
      var er = new TypeError('Invalid non-string/buffer chunk');
      stream.emit('error', er);
      processNextTick(cb, er);
      valid = false;
    }
    return valid;
  }
  
  Writable.prototype.write = function(chunk, encoding, cb) {
    var state = this._writableState;
    var ret = false;
  
    if (typeof encoding === 'function') {
      cb = encoding;
      encoding = null;
    }
  
    if (Buffer.isBuffer(chunk))
      encoding = 'buffer';
    else if (!encoding)
      encoding = state.defaultEncoding;
  
    if (typeof cb !== 'function')
      cb = nop;
  
    if (state.ended)
      writeAfterEnd(this, cb);
    else if (validChunk(this, state, chunk, cb)) {
      state.pendingcb++;
      ret = writeOrBuffer(this, state, chunk, encoding, cb);
    }
  
    return ret;
  };
  
  Writable.prototype.cork = function() {
    var state = this._writableState;
  
    state.corked++;
  };
  
  Writable.prototype.uncork = function() {
    var state = this._writableState;
  
    if (state.corked) {
      state.corked--;
  
      if (!state.writing &&
          !state.corked &&
          !state.finished &&
          !state.bufferProcessing &&
          state.bufferedRequest)
        clearBuffer(this, state);
    }
  };
  
  Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) {
    // node::ParseEncoding() requires lower case.
    if (typeof encoding === 'string')
      encoding = encoding.toLowerCase();
    if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64',
  'ucs2', 'ucs-2','utf16le', 'utf-16le', 'raw']
  .indexOf((encoding + '').toLowerCase()) > -1))
      throw new TypeError('Unknown encoding: ' + encoding);
    this._writableState.defaultEncoding = encoding;
  };
  
  function decodeChunk(state, chunk, encoding) {
    if (!state.objectMode &&
        state.decodeStrings !== false &&
        typeof chunk === 'string') {
      chunk = new Buffer(chunk, encoding);
    }
    return chunk;
  }
  
  // if we're already writing something, then just put this
  // in the queue, and wait our turn.  Otherwise, call _write
  // If we return false, then we need a drain event, so set that flag.
  function writeOrBuffer(stream, state, chunk, encoding, cb) {
    chunk = decodeChunk(state, chunk, encoding);
  
    if (Buffer.isBuffer(chunk))
      encoding = 'buffer';
    var len = state.objectMode ? 1 : chunk.length;
  
    state.length += len;
  
    var ret = state.length < state.highWaterMark;
    // we must ensure that previous needDrain will not be reset to false.
    if (!ret)
      state.needDrain = true;
  
    if (state.writing || state.corked) {
      var last = state.lastBufferedRequest;
      state.lastBufferedRequest = new WriteReq(chunk, encoding, cb);
      if (last) {
        last.next = state.lastBufferedRequest;
      } else {
        state.bufferedRequest = state.lastBufferedRequest;
      }
    } else {
      doWrite(stream, state, false, len, chunk, encoding, cb);
    }
  
    return ret;
  }
  
  function doWrite(stream, state, writev, len, chunk, encoding, cb) {
    state.writelen = len;
    state.writecb = cb;
    state.writing = true;
    state.sync = true;
    if (writev)
      stream._writev(chunk, state.onwrite);
    else
      stream._write(chunk, encoding, state.onwrite);
    state.sync = false;
  }
  
  function onwriteError(stream, state, sync, er, cb) {
    --state.pendingcb;
    if (sync)
      processNextTick(cb, er);
    else
      cb(er);
  
    stream._writableState.errorEmitted = true;
    stream.emit('error', er);
  }
  
  function onwriteStateUpdate(state) {
    state.writing = false;
    state.writecb = null;
    state.length -= state.writelen;
    state.writelen = 0;
  }
  
  function onwrite(stream, er) {
    var state = stream._writableState;
    var sync = state.sync;
    var cb = state.writecb;
  
    onwriteStateUpdate(state);
  
    if (er)
      onwriteError(stream, state, sync, er, cb);
    else {
      // Check if we're actually ready to finish, but don't emit yet
      var finished = needFinish(state);
  
      if (!finished &&
          !state.corked &&
          !state.bufferProcessing &&
          state.bufferedRequest) {
        clearBuffer(stream, state);
      }
  
      if (sync) {
        processNextTick(afterWrite, stream, state, finished, cb);
      } else {
        afterWrite(stream, state, finished, cb);
      }
    }
  }
  
  function afterWrite(stream, state, finished, cb) {
    if (!finished)
      onwriteDrain(stream, state);
    state.pendingcb--;
    cb();
    finishMaybe(stream, state);
  }
  
  // Must force callback to be called on nextTick, so that we don't
  // emit 'drain' before the write() consumer gets the 'false' return
  // value, and has a chance to attach a 'drain' listener.
  function onwriteDrain(stream, state) {
    if (state.length === 0 && state.needDrain) {
      state.needDrain = false;
      stream.emit('drain');
    }
  }
  
  
  // if there's something in the buffer waiting, then process it
  function clearBuffer(stream, state) {
    state.bufferProcessing = true;
    var entry = state.bufferedRequest;
  
    if (stream._writev && entry && entry.next) {
      // Fast case, write everything using _writev()
      var buffer = [];
      var cbs = [];
      while (entry) {
        cbs.push(entry.callback);
        buffer.push(entry);
        entry = entry.next;
      }
  
      // count the one we are adding, as well.
      // TODO(isaacs) clean this up
      state.pendingcb++;
      state.lastBufferedRequest = null;
      doWrite(stream, state, true, state.length, buffer, '', function(err) {
        for (var i = 0; i < cbs.length; i++) {
          state.pendingcb--;
          cbs[i](err);
        }
      });
  
      // Clear buffer
    } else {
      // Slow case, write chunks one-by-one
      while (entry) {
        var chunk = entry.chunk;
        var encoding = entry.encoding;
        var cb = entry.callback;
        var len = state.objectMode ? 1 : chunk.length;
  
        doWrite(stream, state, false, len, chunk, encoding, cb);
        entry = entry.next;
        // if we didn't call the onwrite immediately, then
        // it means that we need to wait until it does.
        // also, that means that the chunk and cb are currently
        // being processed, so move the buffer counter past them.
        if (state.writing) {
          break;
        }
      }
  
      if (entry === null)
        state.lastBufferedRequest = null;
    }
    state.bufferedRequest = entry;
    state.bufferProcessing = false;
  }
  
  Writable.prototype._write = function(chunk, encoding, cb) {
    cb(new Error('not implemented'));
  };
  
  Writable.prototype._writev = null;
  
  Writable.prototype.end = function(chunk, encoding, cb) {
    var state = this._writableState;
  
    if (typeof chunk === 'function') {
      cb = chunk;
      chunk = null;
      encoding = null;
    } else if (typeof encoding === 'function') {
      cb = encoding;
      encoding = null;
    }
  
    if (chunk !== null && chunk !== undefined)
      this.write(chunk, encoding);
  
    // .end() fully uncorks
    if (state.corked) {
      state.corked = 1;
      this.uncork();
    }
  
    // ignore unnecessary end() calls.
    if (!state.ending && !state.finished)
      endWritable(this, state, cb);
  };
  
  
  function needFinish(state) {
    return (state.ending &&
            state.length === 0 &&
            state.bufferedRequest === null &&
            !state.finished &&
            !state.writing);
  }
  
  function prefinish(stream, state) {
    if (!state.prefinished) {
      state.prefinished = true;
      stream.emit('prefinish');
    }
  }
  
  function finishMaybe(stream, state) {
    var need = needFinish(state);
    if (need) {
      if (state.pendingcb === 0) {
        prefinish(stream, state);
        state.finished = true;
        stream.emit('finish');
      } else {
        prefinish(stream, state);
      }
    }
    return need;
  }
  
  function endWritable(stream, state, cb) {
    state.ending = true;
    finishMaybe(stream, state);
    if (cb) {
      if (state.finished)
        processNextTick(cb);
      else
        stream.once('finish', cb);
    }
    state.ended = true;
  }
  
  },{"./_stream_duplex":31,"buffer":15,"core-util-is":36,"events":19,"inherits":21,"process-nextick-args":37,"util-deprecate":38}],36:[function(require,module,exports){
  (function (Buffer){
  // 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
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // 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.
  
  // NOTE: These type checking functions intentionally don't use `instanceof`
  // because it is fragile and can be easily faked with `Object.create()`.
  
  function isArray(arg) {
    if (Array.isArray) {
      return Array.isArray(arg);
    }
    return objectToString(arg) === '[object Array]';
  }
  exports.isArray = isArray;
  
  function isBoolean(arg) {
    return typeof arg === 'boolean';
  }
  exports.isBoolean = isBoolean;
  
  function isNull(arg) {
    return arg === null;
  }
  exports.isNull = isNull;
  
  function isNullOrUndefined(arg) {
    return arg == null;
  }
  exports.isNullOrUndefined = isNullOrUndefined;
  
  function isNumber(arg) {
    return typeof arg === 'number';
  }
  exports.isNumber = isNumber;
  
  function isString(arg) {
    return typeof arg === 'string';
  }
  exports.isString = isString;
  
  function isSymbol(arg) {
    return typeof arg === 'symbol';
  }
  exports.isSymbol = isSymbol;
  
  function isUndefined(arg) {
    return arg === void 0;
  }
  exports.isUndefined = isUndefined;
  
  function isRegExp(re) {
    return objectToString(re) === '[object RegExp]';
  }
  exports.isRegExp = isRegExp;
  
  function isObject(arg) {
    return typeof arg === 'object' && arg !== null;
  }
  exports.isObject = isObject;
  
  function isDate(d) {
    return objectToString(d) === '[object Date]';
  }
  exports.isDate = isDate;
  
  function isError(e) {
    return (objectToString(e) === '[object Error]' || e instanceof Error);
  }
  exports.isError = isError;
  
  function isFunction(arg) {
    return typeof arg === 'function';
  }
  exports.isFunction = isFunction;
  
  function isPrimitive(arg) {
    return arg === null ||
           typeof arg === 'boolean' ||
           typeof arg === 'number' ||
           typeof arg === 'string' ||
           typeof arg === 'symbol' ||  // ES6 symbol
           typeof arg === 'undefined';
  }
  exports.isPrimitive = isPrimitive;
  
  exports.isBuffer = Buffer.isBuffer;
  
  function objectToString(o) {
    return Object.prototype.toString.call(o);
  }
  
  }).call(this,{"isBuffer":require("../../../../insert-module-globals/node_modules/is-buffer/index.js")})
  },{"../../../../insert-module-globals/node_modules/is-buffer/index.js":22}],37:[function(require,module,exports){
  (function (process){
  'use strict';
  
  if (!process.version ||
      process.version.indexOf('v0.') === 0 ||
      process.version.indexOf('v1.') === 0 && process.version.indexOf('v1.8.') !== 0) {
    module.exports = nextTick;
  } else {
    module.exports = process.nextTick;
  }
  
  function nextTick(fn) {
    var args = new Array(arguments.length - 1);
    var i = 0;
    while (i < args.length) {
      args[i++] = arguments[i];
    }
    process.nextTick(function afterTick() {
      fn.apply(null, args);
    });
  }
  
  }).call(this,require('_process'))
  },{"_process":25}],38:[function(require,module,exports){
  (function (global){
  
  /**
   * Module exports.
   */
  
  module.exports = deprecate;
  
  /**
   * Mark that a method should not be used.
   * Returns a modified function which warns once by default.
   *
   * If `localStorage.noDeprecation = true` is set, then it is a no-op.
   *
   * If `localStorage.throwDeprecation = true` is set, then deprecated functions
   * will throw an Error when invoked.
   *
   * If `localStorage.traceDeprecation = true` is set, then deprecated functions
   * will invoke `console.trace()` instead of `console.error()`.
   *
   * @param {Function} fn - the function to deprecate
   * @param {String} msg - the string to print to the console when `fn` is invoked
   * @returns {Function} a new "deprecated" version of `fn`
   * @api public
   */
  
  function deprecate (fn, msg) {
    if (config('noDeprecation')) {
      return fn;
    }
  
    var warned = false;
    function deprecated() {
      if (!warned) {
        if (config('throwDeprecation')) {
          throw new Error(msg);
        } else if (config('traceDeprecation')) {
          console.trace(msg);
        } else {
          console.warn(msg);
        }
        warned = true;
      }
      return fn.apply(this, arguments);
    }
  
    return deprecated;
  }
  
  /**
   * Checks `localStorage` for boolean values for the given `name`.
   *
   * @param {String} name
   * @returns {Boolean}
   * @api private
   */
  
  function config (name) {
    // accessing global.localStorage can trigger a DOMException in sandboxed iframes
    try {
      if (!global.localStorage) return false;
    } catch (_) {
      return false;
    }
    var val = global.localStorage[name];
    if (null == val) return false;
    return String(val).toLowerCase() === 'true';
  }
  
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{}],39:[function(require,module,exports){
  module.exports = require("./lib/_stream_passthrough.js")
  
  },{"./lib/_stream_passthrough.js":32}],40:[function(require,module,exports){
  var Stream = (function (){
    try {
      return require('st' + 'ream'); // hack to fix a circular dependency issue when used with browserify
    } catch(_){}
  }());
  exports = module.exports = require('./lib/_stream_readable.js');
  exports.Stream = Stream || exports;
  exports.Readable = exports;
  exports.Writable = require('./lib/_stream_writable.js');
  exports.Duplex = require('./lib/_stream_duplex.js');
  exports.Transform = require('./lib/_stream_transform.js');
  exports.PassThrough = require('./lib/_stream_passthrough.js');
  
  },{"./lib/_stream_duplex.js":31,"./lib/_stream_passthrough.js":32,"./lib/_stream_readable.js":33,"./lib/_stream_transform.js":34,"./lib/_stream_writable.js":35}],41:[function(require,module,exports){
  module.exports = require("./lib/_stream_transform.js")
  
  },{"./lib/_stream_transform.js":34}],42:[function(require,module,exports){
  module.exports = require("./lib/_stream_writable.js")
  
  },{"./lib/_stream_writable.js":35}],43:[function(require,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,
  // 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
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // 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.
  
  module.exports = Stream;
  
  var EE = require('events').EventEmitter;
  var inherits = require('inherits');
  
  inherits(Stream, EE);
  Stream.Readable = require('readable-stream/readable.js');
  Stream.Writable = require('readable-stream/writable.js');
  Stream.Duplex = require('readable-stream/duplex.js');
  Stream.Transform = require('readable-stream/transform.js');
  Stream.PassThrough = require('readable-stream/passthrough.js');
  
  // Backwards-compat with node 0.4.x
  Stream.Stream = Stream;
  
  
  
  // old-style streams.  Note that the pipe method (the only relevant
  // part of this class) is overridden in the Readable class.
  
  function Stream() {
    EE.call(this);
  }
  
  Stream.prototype.pipe = function(dest, options) {
    var source = this;
  
    function ondata(chunk) {
      if (dest.writable) {
        if (false === dest.write(chunk) && source.pause) {
          source.pause();
        }
      }
    }
  
    source.on('data', ondata);
  
    function ondrain() {
      if (source.readable && source.resume) {
        source.resume();
      }
    }
  
    dest.on('drain', ondrain);
  
    // If the 'end' option is not supplied, dest.end() will be called when
    // source gets the 'end' or 'close' events.  Only dest.end() once.
    if (!dest._isStdio && (!options || options.end !== false)) {
      source.on('end', onend);
      source.on('close', onclose);
    }
  
    var didOnEnd = false;
    function onend() {
      if (didOnEnd) return;
      didOnEnd = true;
  
      dest.end();
    }
  
  
    function onclose() {
      if (didOnEnd) return;
      didOnEnd = true;
  
      if (typeof dest.destroy === 'function') dest.destroy();
    }
  
    // don't leave dangling pipes when there are errors.
    function onerror(er) {
      cleanup();
      if (EE.listenerCount(this, 'error') === 0) {
        throw er; // Unhandled stream error in pipe.
      }
    }
  
    source.on('error', onerror);
    dest.on('error', onerror);
  
    // remove all the event listeners that were added.
    function cleanup() {
      source.removeListener('data', ondata);
      dest.removeListener('drain', ondrain);
  
      source.removeListener('end', onend);
      source.removeListener('close', onclose);
  
      source.removeListener('error', onerror);
      dest.removeListener('error', onerror);
  
      source.removeListener('end', cleanup);
      source.removeListener('close', cleanup);
  
      dest.removeListener('close', cleanup);
    }
  
    source.on('end', cleanup);
    source.on('close', cleanup);
  
    dest.on('close', cleanup);
  
    dest.emit('pipe', source);
  
    // Allow for unix-like usage: A.pipe(B).pipe(C)
    return dest;
  };
  
  },{"events":19,"inherits":21,"readable-stream/duplex.js":30,"readable-stream/passthrough.js":39,"readable-stream/readable.js":40,"readable-stream/transform.js":41,"readable-stream/writable.js":42}],44:[function(require,module,exports){
  var ClientRequest = require('./lib/request')
  var extend = require('xtend')
  var statusCodes = require('builtin-status-codes')
  var url = require('url')
  
  var http = exports
  
  http.request = function (opts, cb) {
  	if (typeof opts === 'string')
  		opts = url.parse(opts)
  	else
  		opts = extend(opts)
  
  	var protocol = opts.protocol || ''
  	var host = opts.hostname || opts.host
  	var port = opts.port
  	var path = opts.path || '/'
  
  	// Necessary for IPv6 addresses
  	if (host && host.indexOf(':') !== -1)
  		host = '[' + host + ']'
  
  	// This may be a relative url. The browser should always be able to interpret it correctly.
  	opts.url = (host ? (protocol + '//' + host) : '') + (port ? ':' + port : '') + path
  	opts.method = (opts.method || 'GET').toUpperCase()
  	opts.headers = opts.headers || {}
  
  	// Also valid opts.auth, opts.mode
  
  	var req = new ClientRequest(opts)
  	if (cb)
  		req.on('response', cb)
  	return req
  }
  
  http.get = function get (opts, cb) {
  	var req = http.request(opts, cb)
  	req.end()
  	return req
  }
  
  http.Agent = function () {}
  http.Agent.defaultMaxSockets = 4
  
  http.STATUS_CODES = statusCodes
  
  http.METHODS = [
  	'CHECKOUT',
  	'CONNECT',
  	'COPY',
  	'DELETE',
  	'GET',
  	'HEAD',
  	'LOCK',
  	'M-SEARCH',
  	'MERGE',
  	'MKACTIVITY',
  	'MKCOL',
  	'MOVE',
  	'NOTIFY',
  	'OPTIONS',
  	'PATCH',
  	'POST',
  	'PROPFIND',
  	'PROPPATCH',
  	'PURGE',
  	'PUT',
  	'REPORT',
  	'SEARCH',
  	'SUBSCRIBE',
  	'TRACE',
  	'UNLOCK',
  	'UNSUBSCRIBE'
  ]
  },{"./lib/request":46,"builtin-status-codes":48,"url":51,"xtend":55}],45:[function(require,module,exports){
  (function (global){
  exports.fetch = isFunction(global.fetch) && isFunction(global.ReadableByteStream)
  
  exports.blobConstructor = false
  try {
  	new Blob([new ArrayBuffer(1)])
  	exports.blobConstructor = true
  } catch (e) {}
  
  var xhr = new global.XMLHttpRequest()
  // If location.host is empty, e.g. if this page/worker was loaded
  // from a Blob, then use example.com to avoid an error
  xhr.open('GET', global.location.host ? '/' : 'https://example.com')
  
  function checkTypeSupport (type) {
  	try {
  		xhr.responseType = type
  		return xhr.responseType === type
  	} catch (e) {}
  	return false
  }
  
  // For some strange reason, Safari 7.0 reports typeof global.ArrayBuffer === 'object'.
  // Safari 7.1 appears to have fixed this bug.
  var haveArrayBuffer = typeof global.ArrayBuffer !== 'undefined'
  var haveSlice = haveArrayBuffer && isFunction(global.ArrayBuffer.prototype.slice)
  
  exports.arraybuffer = haveArrayBuffer && checkTypeSupport('arraybuffer')
  // These next two tests unavoidably show warnings in Chrome. Since fetch will always
  // be used if it's available, just return false for these to avoid the warnings.
  exports.msstream = !exports.fetch && haveSlice && checkTypeSupport('ms-stream')
  exports.mozchunkedarraybuffer = !exports.fetch && haveArrayBuffer &&
  	checkTypeSupport('moz-chunked-arraybuffer')
  exports.overrideMimeType = isFunction(xhr.overrideMimeType)
  exports.vbArray = isFunction(global.VBArray)
  
  function isFunction (value) {
    return typeof value === 'function'
  }
  
  xhr = null // Help gc
  
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{}],46:[function(require,module,exports){
  (function (process,global,Buffer){
  // var Base64 = require('Base64')
  var capability = require('./capability')
  var inherits = require('inherits')
  var response = require('./response')
  var stream = require('stream')
  
  var IncomingMessage = response.IncomingMessage
  var rStates = response.readyStates
  
  function decideMode (preferBinary) {
  	if (capability.fetch) {
  		return 'fetch'
  	} else if (capability.mozchunkedarraybuffer) {
  		return 'moz-chunked-arraybuffer'
  	} else if (capability.msstream) {
  		return 'ms-stream'
  	} else if (capability.arraybuffer && preferBinary) {
  		return 'arraybuffer'
  	} else if (capability.vbArray && preferBinary) {
  		return 'text:vbarray'
  	} else {
  		return 'text'
  	}
  }
  
  var ClientRequest = module.exports = function (opts) {
  	var self = this
  	stream.Writable.call(self)
  
  	self._opts = opts
  	self._body = []
  	self._headers = {}
  	if (opts.auth)
  		self.setHeader('Authorization', 'Basic ' + new Buffer(opts.auth).toString('base64'))
  	Object.keys(opts.headers).forEach(function (name) {
  		self.setHeader(name, opts.headers[name])
  	})
  
  	var preferBinary
  	if (opts.mode === 'prefer-streaming') {
  		// If streaming is a high priority but binary compatibility and
  		// the accuracy of the 'content-type' header aren't
  		preferBinary = false
  	} else if (opts.mode === 'allow-wrong-content-type') {
  		// If streaming is more important than preserving the 'content-type' header
  		preferBinary = !capability.overrideMimeType
  	} else if (!opts.mode || opts.mode === 'default' || opts.mode === 'prefer-fast') {
  		// Use binary if text streaming may corrupt data or the content-type header, or for speed
  		preferBinary = true
  	} else {
  		throw new Error('Invalid value for opts.mode')
  	}
  	self._mode = decideMode(preferBinary)
  
  	self.on('finish', function () {
  		self._onFinish()
  	})
  }
  
  inherits(ClientRequest, stream.Writable)
  
  ClientRequest.prototype.setHeader = function (name, value) {
  	var self = this
  	var lowerName = name.toLowerCase()
  	// This check is not necessary, but it prevents warnings from browsers about setting unsafe
  	// headers. To be honest I'm not entirely sure hiding these warnings is a good thing, but
  	// http-browserify did it, so I will too.
  	if (unsafeHeaders.indexOf(lowerName) !== -1)
  		return
  
  	self._headers[lowerName] = {
  		name: name,
  		value: value
  	}
  }
  
  ClientRequest.prototype.getHeader = function (name) {
  	var self = this
  	return self._headers[name.toLowerCase()].value
  }
  
  ClientRequest.prototype.removeHeader = function (name) {
  	var self = this
  	delete self._headers[name.toLowerCase()]
  }
  
  ClientRequest.prototype._onFinish = function () {
  	var self = this
  
  	if (self._destroyed)
  		return
  	var opts = self._opts
  
  	var headersObj = self._headers
  	var body
  	if (opts.method === 'POST' || opts.method === 'PUT' || opts.method === 'PATCH') {
  		if (capability.blobConstructor) {
  			body = new global.Blob(self._body.map(function (buffer) {
  				return buffer.toArrayBuffer()
  			}), {
  				type: (headersObj['content-type'] || {}).value || ''
  			})
  		} else {
  			// get utf8 string
  			body = Buffer.concat(self._body).toString()
  		}
  	}
  
  	if (self._mode === 'fetch') {
  		var headers = Object.keys(headersObj).map(function (name) {
  			return [headersObj[name].name, headersObj[name].value]
  		})
  
  		global.fetch(self._opts.url, {
  			method: self._opts.method,
  			headers: headers,
  			body: body,
  			mode: 'cors',
  			credentials: opts.withCredentials ? 'include' : 'same-origin'
  		}).then(function (response) {
  			self._fetchResponse = response
  			self._connect()
  		}, function (reason) {
  			self.emit('error', reason)
  		})
  	} else {
  		var xhr = self._xhr = new global.XMLHttpRequest()
  		try {
  			xhr.open(self._opts.method, self._opts.url, true)
  		} catch (err) {
  			process.nextTick(function () {
  				self.emit('error', err)
  			})
  			return
  		}
  
  		// Can't set responseType on really old browsers
  		if ('responseType' in xhr)
  			xhr.responseType = self._mode.split(':')[0]
  
  		if ('withCredentials' in xhr)
  			xhr.withCredentials = !!opts.withCredentials
  
  		if (self._mode === 'text' && 'overrideMimeType' in xhr)
  			xhr.overrideMimeType('text/plain; charset=x-user-defined')
  
  		Object.keys(headersObj).forEach(function (name) {
  			xhr.setRequestHeader(headersObj[name].name, headersObj[name].value)
  		})
  
  		self._response = null
  		xhr.onreadystatechange = function () {
  			switch (xhr.readyState) {
  				case rStates.LOADING:
  				case rStates.DONE:
  					self._onXHRProgress()
  					break
  			}
  		}
  		// Necessary for streaming in Firefox, since xhr.response is ONLY defined
  		// in onprogress, not in onreadystatechange with xhr.readyState = 3
  		if (self._mode === 'moz-chunked-arraybuffer') {
  			xhr.onprogress = function () {
  				self._onXHRProgress()
  			}
  		}
  
  		xhr.onerror = function () {
  			if (self._destroyed)
  				return
  			self.emit('error', new Error('XHR error'))
  		}
  
  		try {
  			xhr.send(body)
  		} catch (err) {
  			process.nextTick(function () {
  				self.emit('error', err)
  			})
  			return
  		}
  	}
  }
  
  /**
   * Checks if xhr.status is readable. Even though the spec says it should
   * be available in readyState 3, accessing it throws an exception in IE8
   */
  function statusValid (xhr) {
  	try {
  		return (xhr.status !== null)
  	} catch (e) {
  		return false
  	}
  }
  
  ClientRequest.prototype._onXHRProgress = function () {
  	var self = this
  
  	if (!statusValid(self._xhr) || self._destroyed)
  		return
  
  	if (!self._response)
  		self._connect()
  
  	self._response._onXHRProgress()
  }
  
  ClientRequest.prototype._connect = function () {
  	var self = this
  
  	if (self._destroyed)
  		return
  
  	self._response = new IncomingMessage(self._xhr, self._fetchResponse, self._mode)
  	self.emit('response', self._response)
  }
  
  ClientRequest.prototype._write = function (chunk, encoding, cb) {
  	var self = this
  
  	self._body.push(chunk)
  	cb()
  }
  
  ClientRequest.prototype.abort = ClientRequest.prototype.destroy = function () {
  	var self = this
  	self._destroyed = true
  	if (self._response)
  		self._response._destroyed = true
  	if (self._xhr)
  		self._xhr.abort()
  	// Currently, there isn't a way to truly abort a fetch.
  	// If you like bikeshedding, see https://github.com/whatwg/fetch/issues/27
  }
  
  ClientRequest.prototype.end = function (data, encoding, cb) {
  	var self = this
  	if (typeof data === 'function') {
  		cb = data
  		data = undefined
  	}
  
  	stream.Writable.prototype.end.call(self, data, encoding, cb)
  }
  
  ClientRequest.prototype.flushHeaders = function () {}
  ClientRequest.prototype.setTimeout = function () {}
  ClientRequest.prototype.setNoDelay = function () {}
  ClientRequest.prototype.setSocketKeepAlive = function () {}
  
  // Taken from http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader%28%29-method
  var unsafeHeaders = [
  	'accept-charset',
  	'accept-encoding',
  	'access-control-request-headers',
  	'access-control-request-method',
  	'connection',
  	'content-length',
  	'cookie',
  	'cookie2',
  	'date',
  	'dnt',
  	'expect',
  	'host',
  	'keep-alive',
  	'origin',
  	'referer',
  	'te',
  	'trailer',
  	'transfer-encoding',
  	'upgrade',
  	'user-agent',
  	'via'
  ]
  
  }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer)
  },{"./capability":45,"./response":47,"_process":25,"buffer":15,"inherits":21,"stream":43}],47:[function(require,module,exports){
  (function (process,global,Buffer){
  var capability = require('./capability')
  var inherits = require('inherits')
  var stream = require('stream')
  
  var rStates = exports.readyStates = {
  	UNSENT: 0,
  	OPENED: 1,
  	HEADERS_RECEIVED: 2,
  	LOADING: 3,
  	DONE: 4
  }
  
  var IncomingMessage = exports.IncomingMessage = function (xhr, response, mode) {
  	var self = this
  	stream.Readable.call(self)
  
  	self._mode = mode
  	self.headers = {}
  	self.rawHeaders = []
  	self.trailers = {}
  	self.rawTrailers = []
  
  	// Fake the 'close' event, but only once 'end' fires
  	self.on('end', function () {
  		// The nextTick is necessary to prevent the 'request' module from causing an infinite loop
  		process.nextTick(function () {
  			self.emit('close')
  		})
  	})
  
  	if (mode === 'fetch') {
  		self._fetchResponse = response
  
  		self.statusCode = response.status
  		self.statusMessage = response.statusText
  		// backwards compatible version of for (<item> of <iterable>):
  		// for (var <item>,_i,_it = <iterable>[Symbol.iterator](); <item> = (_i = _it.next()).value,!_i.done;)
  		for (var header, _i, _it = response.headers[Symbol.iterator](); header = (_i = _it.next()).value, !_i.done;) {
  			self.headers[header[0].toLowerCase()] = header[1]
  			self.rawHeaders.push(header[0], header[1])
  		}
  
  		// TODO: this doesn't respect backpressure. Once WritableStream is available, this can be fixed
  		var reader = response.body.getReader()
  		function read () {
  			reader.read().then(function (result) {
  				if (self._destroyed)
  					return
  				if (result.done) {
  					self.push(null)
  					return
  				}
  				self.push(new Buffer(result.value))
  				read()
  			})
  		}
  		read()
  
  	} else {
  		self._xhr = xhr
  		self._pos = 0
  
  		self.statusCode = xhr.status
  		self.statusMessage = xhr.statusText
  		var headers = xhr.getAllResponseHeaders().split(/\r?\n/)
  		headers.forEach(function (header) {
  			var matches = header.match(/^([^:]+):\s*(.*)/)
  			if (matches) {
  				var key = matches[1].toLowerCase()
  				if (self.headers[key] !== undefined)
  					self.headers[key] += ', ' + matches[2]
  				else
  					self.headers[key] = matches[2]
  				self.rawHeaders.push(matches[1], matches[2])
  			}
  		})
  
  		self._charset = 'x-user-defined'
  		if (!capability.overrideMimeType) {
  			var mimeType = self.rawHeaders['mime-type']
  			if (mimeType) {
  				var charsetMatch = mimeType.match(/;\s*charset=([^;])(;|$)/)
  				if (charsetMatch) {
  					self._charset = charsetMatch[1].toLowerCase()
  				}
  			}
  			if (!self._charset)
  				self._charset = 'utf-8' // best guess
  		}
  	}
  }
  
  inherits(IncomingMessage, stream.Readable)
  
  IncomingMessage.prototype._read = function () {}
  
  IncomingMessage.prototype._onXHRProgress = function () {
  	var self = this
  
  	var xhr = self._xhr
  
  	var response = null
  	switch (self._mode) {
  		case 'text:vbarray': // For IE9
  			if (xhr.readyState !== rStates.DONE)
  				break
  			try {
  				// This fails in IE8
  				response = new global.VBArray(xhr.responseBody).toArray()
  			} catch (e) {}
  			if (response !== null) {
  				self.push(new Buffer(response))
  				break
  			}
  			// Falls through in IE8	
  		case 'text':
  			try { // This will fail when readyState = 3 in IE9. Switch mode and wait for readyState = 4
  				response = xhr.responseText
  			} catch (e) {
  				self._mode = 'text:vbarray'
  				break
  			}
  			if (response.length > self._pos) {
  				var newData = response.substr(self._pos)
  				if (self._charset === 'x-user-defined') {
  					var buffer = new Buffer(newData.length)
  					for (var i = 0; i < newData.length; i++)
  						buffer[i] = newData.charCodeAt(i) & 0xff
  
  					self.push(buffer)
  				} else {
  					self.push(newData, self._charset)
  				}
  				self._pos = response.length
  			}
  			break
  		case 'arraybuffer':
  			if (xhr.readyState !== rStates.DONE)
  				break
  			response = xhr.response
  			self.push(new Buffer(new Uint8Array(response)))
  			break
  		case 'moz-chunked-arraybuffer': // take whole
  			response = xhr.response
  			if (xhr.readyState !== rStates.LOADING || !response)
  				break
  			self.push(new Buffer(new Uint8Array(response)))
  			break
  		case 'ms-stream':
  			response = xhr.response
  			if (xhr.readyState !== rStates.LOADING)
  				break
  			var reader = new global.MSStreamReader()
  			reader.onprogress = function () {
  				if (reader.result.byteLength > self._pos) {
  					self.push(new Buffer(new Uint8Array(reader.result.slice(self._pos))))
  					self._pos = reader.result.byteLength
  				}
  			}
  			reader.onload = function () {
  				self.push(null)
  			}
  			// reader.onerror = ??? // TODO: this
  			reader.readAsArrayBuffer(response)
  			break
  	}
  
  	// The ms-stream case handles end separately in reader.onload()
  	if (self._xhr.readyState === rStates.DONE && self._mode !== 'ms-stream') {
  		self.push(null)
  	}
  }
  
  }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer)
  },{"./capability":45,"_process":25,"buffer":15,"inherits":21,"stream":43}],48:[function(require,module,exports){
  module.exports = {
    "100": "Continue",
    "101": "Switching Protocols",
    "102": "Processing",
    "200": "OK",
    "201": "Created",
    "202": "Accepted",
    "203": "Non-Authoritative Information",
    "204": "No Content",
    "205": "Reset Content",
    "206": "Partial Content",
    "207": "Multi-Status",
    "300": "Multiple Choices",
    "301": "Moved Permanently",
    "302": "Moved Temporarily",
    "303": "See Other",
    "304": "Not Modified",
    "305": "Use Proxy",
    "307": "Temporary Redirect",
    "308": "Permanent Redirect",
    "400": "Bad Request",
    "401": "Unauthorized",
    "402": "Payment Required",
    "403": "Forbidden",
    "404": "Not Found",
    "405": "Method Not Allowed",
    "406": "Not Acceptable",
    "407": "Proxy Authentication Required",
    "408": "Request Time-out",
    "409": "Conflict",
    "410": "Gone",
    "411": "Length Required",
    "412": "Precondition Failed",
    "413": "Request Entity Too Large",
    "414": "Request-URI Too Large",
    "415": "Unsupported Media Type",
    "416": "Requested Range Not Satisfiable",
    "417": "Expectation Failed",
    "418": "I'm a teapot",
    "422": "Unprocessable Entity",
    "423": "Locked",
    "424": "Failed Dependency",
    "425": "Unordered Collection",
    "426": "Upgrade Required",
    "428": "Precondition Required",
    "429": "Too Many Requests",
    "431": "Request Header Fields Too Large",
    "500": "Internal Server Error",
    "501": "Not Implemented",
    "502": "Bad Gateway",
    "503": "Service Unavailable",
    "504": "Gateway Time-out",
    "505": "HTTP Version Not Supported",
    "506": "Variant Also Negotiates",
    "507": "Insufficient Storage",
    "509": "Bandwidth Limit Exceeded",
    "510": "Not Extended",
    "511": "Network Authentication Required"
  }
  
  },{}],49:[function(require,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,
  // 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
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // 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 Buffer = require('buffer').Buffer;
  
  var isBufferEncoding = Buffer.isEncoding
    || function(encoding) {
         switch (encoding && encoding.toLowerCase()) {
           case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true;
           default: return false;
         }
       }
  
  
  function assertEncoding(encoding) {
    if (encoding && !isBufferEncoding(encoding)) {
      throw new Error('Unknown encoding: ' + encoding);
    }
  }
  
  // StringDecoder provides an interface for efficiently splitting a series of
  // buffers into a series of JS strings without breaking apart multi-byte
  // characters. CESU-8 is handled as part of the UTF-8 encoding.
  //
  // @TODO Handling all encodings inside a single object makes it very difficult
  // to reason about this code, so it should be split up in the future.
  // @TODO There should be a utf8-strict encoding that rejects invalid UTF-8 code
  // points as used by CESU-8.
  var StringDecoder = exports.StringDecoder = function(encoding) {
    this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, '');
    assertEncoding(encoding);
    switch (this.encoding) {
      case 'utf8':
        // CESU-8 represents each of Surrogate Pair by 3-bytes
        this.surrogateSize = 3;
        break;
      case 'ucs2':
      case 'utf16le':
        // UTF-16 represents each of Surrogate Pair by 2-bytes
        this.surrogateSize = 2;
        this.detectIncompleteChar = utf16DetectIncompleteChar;
        break;
      case 'base64':
        // Base-64 stores 3 bytes in 4 chars, and pads the remainder.
        this.surrogateSize = 3;
        this.detectIncompleteChar = base64DetectIncompleteChar;
        break;
      default:
        this.write = passThroughWrite;
        return;
    }
  
    // Enough space to store all bytes of a single character. UTF-8 needs 4
    // bytes, but CESU-8 may require up to 6 (3 bytes per surrogate).
    this.charBuffer = new Buffer(6);
    // Number of bytes received for the current incomplete multi-byte character.
    this.charReceived = 0;
    // Number of bytes expected for the current incomplete multi-byte character.
    this.charLength = 0;
  };
  
  
  // write decodes the given buffer and returns it as JS string that is
  // guaranteed to not contain any partial multi-byte characters. Any partial
  // character found at the end of the buffer is buffered up, and will be
  // returned when calling write again with the remaining bytes.
  //
  // Note: Converting a Buffer containing an orphan surrogate to a String
  // currently works, but converting a String to a Buffer (via `new Buffer`, or
  // Buffer#write) will replace incomplete surrogates with the unicode
  // replacement character. See https://codereview.chromium.org/121173009/ .
  StringDecoder.prototype.write = function(buffer) {
    var charStr = '';
    // if our last write ended with an incomplete multibyte character
    while (this.charLength) {
      // determine how many remaining bytes this buffer has to offer for this char
      var available = (buffer.length >= this.charLength - this.charReceived) ?
          this.charLength - this.charReceived :
          buffer.length;
  
      // add the new bytes to the char buffer
      buffer.copy(this.charBuffer, this.charReceived, 0, available);
      this.charReceived += available;
  
      if (this.charReceived < this.charLength) {
        // still not enough chars in this buffer? wait for more ...
        return '';
      }
  
      // remove bytes belonging to the current character from the buffer
      buffer = buffer.slice(available, buffer.length);
  
      // get the character that was split
      charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding);
  
      // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
      var charCode = charStr.charCodeAt(charStr.length - 1);
      if (charCode >= 0xD800 && charCode <= 0xDBFF) {
        this.charLength += this.surrogateSize;
        charStr = '';
        continue;
      }
      this.charReceived = this.charLength = 0;
  
      // if there are no more bytes in this buffer, just emit our char
      if (buffer.length === 0) {
        return charStr;
      }
      break;
    }
  
    // determine and set charLength / charReceived
    this.detectIncompleteChar(buffer);
  
    var end = buffer.length;
    if (this.charLength) {
      // buffer the incomplete character bytes we got
      buffer.copy(this.charBuffer, 0, buffer.length - this.charReceived, end);
      end -= this.charReceived;
    }
  
    charStr += buffer.toString(this.encoding, 0, end);
  
    var end = charStr.length - 1;
    var charCode = charStr.charCodeAt(end);
    // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
    if (charCode >= 0xD800 && charCode <= 0xDBFF) {
      var size = this.surrogateSize;
      this.charLength += size;
      this.charReceived += size;
      this.charBuffer.copy(this.charBuffer, size, 0, size);
      buffer.copy(this.charBuffer, 0, 0, size);
      return charStr.substring(0, end);
    }
  
    // or just emit the charStr
    return charStr;
  };
  
  // detectIncompleteChar determines if there is an incomplete UTF-8 character at
  // the end of the given buffer. If so, it sets this.charLength to the byte
  // length that character, and sets this.charReceived to the number of bytes
  // that are available for this character.
  StringDecoder.prototype.detectIncompleteChar = function(buffer) {
    // determine how many bytes we have to check at the end of this buffer
    var i = (buffer.length >= 3) ? 3 : buffer.length;
  
    // Figure out if one of the last i bytes of our buffer announces an
    // incomplete char.
    for (; i > 0; i--) {
      var c = buffer[buffer.length - i];
  
      // See http://en.wikipedia.org/wiki/UTF-8#Description
  
      // 110XXXXX
      if (i == 1 && c >> 5 == 0x06) {
        this.charLength = 2;
        break;
      }
  
      // 1110XXXX
      if (i <= 2 && c >> 4 == 0x0E) {
        this.charLength = 3;
        break;
      }
  
      // 11110XXX
      if (i <= 3 && c >> 3 == 0x1E) {
        this.charLength = 4;
        break;
      }
    }
    this.charReceived = i;
  };
  
  StringDecoder.prototype.end = function(buffer) {
    var res = '';
    if (buffer && buffer.length)
      res = this.write(buffer);
  
    if (this.charReceived) {
      var cr = this.charReceived;
      var buf = this.charBuffer;
      var enc = this.encoding;
      res += buf.slice(0, cr).toString(enc);
    }
  
    return res;
  };
  
  function passThroughWrite(buffer) {
    return buffer.toString(this.encoding);
  }
  
  function utf16DetectIncompleteChar(buffer) {
    this.charReceived = buffer.length % 2;
    this.charLength = this.charReceived ? 2 : 0;
  }
  
  function base64DetectIncompleteChar(buffer) {
    this.charReceived = buffer.length % 3;
    this.charLength = this.charReceived ? 3 : 0;
  }
  
  },{"buffer":15}],50:[function(require,module,exports){
  var nextTick = require('process/browser.js').nextTick;
  var apply = Function.prototype.apply;
  var slice = Array.prototype.slice;
  var immediateIds = {};
  var nextImmediateId = 0;
  
  // DOM APIs, for completeness
  
  exports.setTimeout = function() {
    return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout);
  };
  exports.setInterval = function() {
    return new Timeout(apply.call(setInterval, window, arguments), clearInterval);
  };
  exports.clearTimeout =
  exports.clearInterval = function(timeout) { timeout.close(); };
  
  function Timeout(id, clearFn) {
    this._id = id;
    this._clearFn = clearFn;
  }
  Timeout.prototype.unref = Timeout.prototype.ref = function() {};
  Timeout.prototype.close = function() {
    this._clearFn.call(window, this._id);
  };
  
  // Does not start the time, just sets up the members needed.
  exports.enroll = function(item, msecs) {
    clearTimeout(item._idleTimeoutId);
    item._idleTimeout = msecs;
  };
  
  exports.unenroll = function(item) {
    clearTimeout(item._idleTimeoutId);
    item._idleTimeout = -1;
  };
  
  exports._unrefActive = exports.active = function(item) {
    clearTimeout(item._idleTimeoutId);
  
    var msecs = item._idleTimeout;
    if (msecs >= 0) {
      item._idleTimeoutId = setTimeout(function onTimeout() {
        if (item._onTimeout)
          item._onTimeout();
      }, msecs);
    }
  };
  
  // That's not how node.js implements it but the exposed api is the same.
  exports.setImmediate = typeof setImmediate === "function" ? setImmediate : function(fn) {
    var id = nextImmediateId++;
    var args = arguments.length < 2 ? false : slice.call(arguments, 1);
  
    immediateIds[id] = true;
  
    nextTick(function onNextTick() {
      if (immediateIds[id]) {
        // fn.call() is faster so we optimize for the common use-case
        // @see http://jsperf.com/call-apply-segu
        if (args) {
          fn.apply(null, args);
        } else {
          fn.call(null);
        }
        // Prevent ids from leaking
        exports.clearImmediate(id);
      }
    });
  
    return id;
  };
  
  exports.clearImmediate = typeof clearImmediate === "function" ? clearImmediate : function(id) {
    delete immediateIds[id];
  };
  },{"process/browser.js":25}],51:[function(require,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,
  // 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
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // 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.
  
  'use strict';
  
  var punycode = require('punycode');
  var util = require('./util');
  
  exports.parse = urlParse;
  exports.resolve = urlResolve;
  exports.resolveObject = urlResolveObject;
  exports.format = urlFormat;
  
  exports.Url = Url;
  
  function Url() {
    this.protocol = null;
    this.slashes = null;
    this.auth = null;
    this.host = null;
    this.port = null;
    this.hostname = null;
    this.hash = null;
    this.search = null;
    this.query = null;
    this.pathname = null;
    this.path = null;
    this.href = null;
  }
  
  // Reference: RFC 3986, RFC 1808, RFC 2396
  
  // define these here so at least they only have to be
  // compiled once on the first module load.
  var protocolPattern = /^([a-z0-9.+-]+:)/i,
      portPattern = /:[0-9]*$/,
  
      // Special case for a simple path URL
      simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,
  
      // RFC 2396: characters reserved for delimiting URLs.
      // We actually just auto-escape these.
      delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'],
  
      // RFC 2396: characters not allowed for various reasons.
      unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims),
  
      // Allowed by RFCs, but cause of XSS attacks.  Always escape these.
      autoEscape = ['\''].concat(unwise),
      // Characters that are never ever allowed in a hostname.
      // Note that any invalid chars are also handled, but these
      // are the ones that are *expected* to be seen, so we fast-path
      // them.
      nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape),
      hostEndingChars = ['/', '?', '#'],
      hostnameMaxLen = 255,
      hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/,
      hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/,
      // protocols that can allow "unsafe" and "unwise" chars.
      unsafeProtocol = {
        'javascript': true,
        'javascript:': true
      },
      // protocols that never have a hostname.
      hostlessProtocol = {
        'javascript': true,
        'javascript:': true
      },
      // protocols that always contain a // bit.
      slashedProtocol = {
        'http': true,
        'https': true,
        'ftp': true,
        'gopher': true,
        'file': true,
        'http:': true,
        'https:': true,
        'ftp:': true,
        'gopher:': true,
        'file:': true
      },
      querystring = require('querystring');
  
  function urlParse(url, parseQueryString, slashesDenoteHost) {
    if (url && util.isObject(url) && url instanceof Url) return url;
  
    var u = new Url;
    u.parse(url, parseQueryString, slashesDenoteHost);
    return u;
  }
  
  Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
    if (!util.isString(url)) {
      throw new TypeError("Parameter 'url' must be a string, not " + typeof url);
    }
  
    // Copy chrome, IE, opera backslash-handling behavior.
    // Back slashes before the query string get converted to forward slashes
    // See: https://code.google.com/p/chromium/issues/detail?id=25916
    var queryIndex = url.indexOf('?'),
        splitter =
            (queryIndex !== -1 && queryIndex < url.indexOf('#')) ? '?' : '#',
        uSplit = url.split(splitter),
        slashRegex = /\\/g;
    uSplit[0] = uSplit[0].replace(slashRegex, '/');
    url = uSplit.join(splitter);
  
    var rest = url;
  
    // trim before proceeding.
    // This is to support parse stuff like "  http://foo.com  \n"
    rest = rest.trim();
  
    if (!slashesDenoteHost && url.split('#').length === 1) {
      // Try fast path regexp
      var simplePath = simplePathPattern.exec(rest);
      if (simplePath) {
        this.path = rest;
        this.href = rest;
        this.pathname = simplePath[1];
        if (simplePath[2]) {
          this.search = simplePath[2];
          if (parseQueryString) {
            this.query = querystring.parse(this.search.substr(1));
          } else {
            this.query = this.search.substr(1);
          }
        } else if (parseQueryString) {
          this.search = '';
          this.query = {};
        }
        return this;
      }
    }
  
    var proto = protocolPattern.exec(rest);
    if (proto) {
      proto = proto[0];
      var lowerProto = proto.toLowerCase();
      this.protocol = lowerProto;
      rest = rest.substr(proto.length);
    }
  
    // figure out if it's got a host
    // user@server is *always* interpreted as a hostname, and url
    // resolution will treat //foo/bar as host=foo,path=bar because that's
    // how the browser resolves relative URLs.
    if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
      var slashes = rest.substr(0, 2) === '//';
      if (slashes && !(proto && hostlessProtocol[proto])) {
        rest = rest.substr(2);
        this.slashes = true;
      }
    }
  
    if (!hostlessProtocol[proto] &&
        (slashes || (proto && !slashedProtocol[proto]))) {
  
      // there's a hostname.
      // the first instance of /, ?, ;, or # ends the host.
      //
      // If there is an @ in the hostname, then non-host chars *are* allowed
      // to the left of the last @ sign, unless some host-ending character
      // comes *before* the @-sign.
      // URLs are obnoxious.
      //
      // ex:
      // http://a@b@c/ => user:a@b host:c
      // http://a@b?@c => user:a host:c path:/?@c
  
      // v0.12 TODO(isaacs): This is not quite how Chrome does things.
      // Review our test case against browsers more comprehensively.
  
      // find the first instance of any hostEndingChars
      var hostEnd = -1;
      for (var i = 0; i < hostEndingChars.length; i++) {
        var hec = rest.indexOf(hostEndingChars[i]);
        if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
          hostEnd = hec;
      }
  
      // at this point, either we have an explicit point where the
      // auth portion cannot go past, or the last @ char is the decider.
      var auth, atSign;
      if (hostEnd === -1) {
        // atSign can be anywhere.
        atSign = rest.lastIndexOf('@');
      } else {
        // atSign must be in auth portion.
        // http://a@b/c@d => host:b auth:a path:/c@d
        atSign = rest.lastIndexOf('@', hostEnd);
      }
  
      // Now we have a portion which is definitely the auth.
      // Pull that off.
      if (atSign !== -1) {
        auth = rest.slice(0, atSign);
        rest = rest.slice(atSign + 1);
        this.auth = decodeURIComponent(auth);
      }
  
      // the host is the remaining to the left of the first non-host char
      hostEnd = -1;
      for (var i = 0; i < nonHostChars.length; i++) {
        var hec = rest.indexOf(nonHostChars[i]);
        if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
          hostEnd = hec;
      }
      // if we still have not hit it, then the entire thing is a host.
      if (hostEnd === -1)
        hostEnd = rest.length;
  
      this.host = rest.slice(0, hostEnd);
      rest = rest.slice(hostEnd);
  
      // pull out port.
      this.parseHost();
  
      // we've indicated that there is a hostname,
      // so even if it's empty, it has to be present.
      this.hostname = this.hostname || '';
  
      // if hostname begins with [ and ends with ]
      // assume that it's an IPv6 address.
      var ipv6Hostname = this.hostname[0] === '[' &&
          this.hostname[this.hostname.length - 1] === ']';
  
      // validate a little.
      if (!ipv6Hostname) {
        var hostparts = this.hostname.split(/\./);
        for (var i = 0, l = hostparts.length; i < l; i++) {
          var part = hostparts[i];
          if (!part) continue;
          if (!part.match(hostnamePartPattern)) {
            var newpart = '';
            for (var j = 0, k = part.length; j < k; j++) {
              if (part.charCodeAt(j) > 127) {
                // we replace non-ASCII char with a temporary placeholder
                // we need this to make sure size of hostname is not
                // broken by replacing non-ASCII by nothing
                newpart += 'x';
              } else {
                newpart += part[j];
              }
            }
            // we test again with ASCII char only
            if (!newpart.match(hostnamePartPattern)) {
              var validParts = hostparts.slice(0, i);
              var notHost = hostparts.slice(i + 1);
              var bit = part.match(hostnamePartStart);
              if (bit) {
                validParts.push(bit[1]);
                notHost.unshift(bit[2]);
              }
              if (notHost.length) {
                rest = '/' + notHost.join('.') + rest;
              }
              this.hostname = validParts.join('.');
              break;
            }
          }
        }
      }
  
      if (this.hostname.length > hostnameMaxLen) {
        this.hostname = '';
      } else {
        // hostnames are always lower case.
        this.hostname = this.hostname.toLowerCase();
      }
  
      if (!ipv6Hostname) {
        // IDNA Support: Returns a punycoded representation of "domain".
        // It only converts parts of the domain name that
        // have non-ASCII characters, i.e. it doesn't matter if
        // you call it with a domain that already is ASCII-only.
        this.hostname = punycode.toASCII(this.hostname);
      }
  
      var p = this.port ? ':' + this.port : '';
      var h = this.hostname || '';
      this.host = h + p;
      this.href += this.host;
  
      // strip [ and ] from the hostname
      // the host field still retains them, though
      if (ipv6Hostname) {
        this.hostname = this.hostname.substr(1, this.hostname.length - 2);
        if (rest[0] !== '/') {
          rest = '/' + rest;
        }
      }
    }
  
    // now rest is set to the post-host stuff.
    // chop off any delim chars.
    if (!unsafeProtocol[lowerProto]) {
  
      // First, make 100% sure that any "autoEscape" chars get
      // escaped, even if encodeURIComponent doesn't think they
      // need to be.
      for (var i = 0, l = autoEscape.length; i < l; i++) {
        var ae = autoEscape[i];
        if (rest.indexOf(ae) === -1)
          continue;
        var esc = encodeURIComponent(ae);
        if (esc === ae) {
          esc = escape(ae);
        }
        rest = rest.split(ae).join(esc);
      }
    }
  
  
    // chop off from the tail first.
    var hash = rest.indexOf('#');
    if (hash !== -1) {
      // got a fragment string.
      this.hash = rest.substr(hash);
      rest = rest.slice(0, hash);
    }
    var qm = rest.indexOf('?');
    if (qm !== -1) {
      this.search = rest.substr(qm);
      this.query = rest.substr(qm + 1);
      if (parseQueryString) {
        this.query = querystring.parse(this.query);
      }
      rest = rest.slice(0, qm);
    } else if (parseQueryString) {
      // no query string, but parseQueryString still requested
      this.search = '';
      this.query = {};
    }
    if (rest) this.pathname = rest;
    if (slashedProtocol[lowerProto] &&
        this.hostname && !this.pathname) {
      this.pathname = '/';
    }
  
    //to support http.request
    if (this.pathname || this.search) {
      var p = this.pathname || '';
      var s = this.search || '';
      this.path = p + s;
    }
  
    // finally, reconstruct the href based on what has been validated.
    this.href = this.format();
    return this;
  };
  
  // format a parsed object into a url string
  function urlFormat(obj) {
    // ensure it's an object, and not a string url.
    // If it's an obj, this is a no-op.
    // this way, you can call url_format() on strings
    // to clean up potentially wonky urls.
    if (util.isString(obj)) obj = urlParse(obj);
    if (!(obj instanceof Url)) return Url.prototype.format.call(obj);
    return obj.format();
  }
  
  Url.prototype.format = function() {
    var auth = this.auth || '';
    if (auth) {
      auth = encodeURIComponent(auth);
      auth = auth.replace(/%3A/i, ':');
      auth += '@';
    }
  
    var protocol = this.protocol || '',
        pathname = this.pathname || '',
        hash = this.hash || '',
        host = false,
        query = '';
  
    if (this.host) {
      host = auth + this.host;
    } else if (this.hostname) {
      host = auth + (this.hostname.indexOf(':') === -1 ?
          this.hostname :
          '[' + this.hostname + ']');
      if (this.port) {
        host += ':' + this.port;
      }
    }
  
    if (this.query &&
        util.isObject(this.query) &&
        Object.keys(this.query).length) {
      query = querystring.stringify(this.query);
    }
  
    var search = this.search || (query && ('?' + query)) || '';
  
    if (protocol && protocol.substr(-1) !== ':') protocol += ':';
  
    // only the slashedProtocols get the //.  Not mailto:, xmpp:, etc.
    // unless they had them to begin with.
    if (this.slashes ||
        (!protocol || slashedProtocol[protocol]) && host !== false) {
      host = '//' + (host || '');
      if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname;
    } else if (!host) {
      host = '';
    }
  
    if (hash && hash.charAt(0) !== '#') hash = '#' + hash;
    if (search && search.charAt(0) !== '?') search = '?' + search;
  
    pathname = pathname.replace(/[?#]/g, function(match) {
      return encodeURIComponent(match);
    });
    search = search.replace('#', '%23');
  
    return protocol + host + pathname + search + hash;
  };
  
  function urlResolve(source, relative) {
    return urlParse(source, false, true).resolve(relative);
  }
  
  Url.prototype.resolve = function(relative) {
    return this.resolveObject(urlParse(relative, false, true)).format();
  };
  
  function urlResolveObject(source, relative) {
    if (!source) return relative;
    return urlParse(source, false, true).resolveObject(relative);
  }
  
  Url.prototype.resolveObject = function(relative) {
    if (util.isString(relative)) {
      var rel = new Url();
      rel.parse(relative, false, true);
      relative = rel;
    }
  
    var result = new Url();
    var tkeys = Object.keys(this);
    for (var tk = 0; tk < tkeys.length; tk++) {
      var tkey = tkeys[tk];
      result[tkey] = this[tkey];
    }
  
    // hash is always overridden, no matter what.
    // even href="" will remove it.
    result.hash = relative.hash;
  
    // if the relative url is empty, then there's nothing left to do here.
    if (relative.href === '') {
      result.href = result.format();
      return result;
    }
  
    // hrefs like //foo/bar always cut to the protocol.
    if (relative.slashes && !relative.protocol) {
      // take everything except the protocol from relative
      var rkeys = Object.keys(relative);
      for (var rk = 0; rk < rkeys.length; rk++) {
        var rkey = rkeys[rk];
        if (rkey !== 'protocol')
          result[rkey] = relative[rkey];
      }
  
      //urlParse appends trailing / to urls like http://www.example.com
      if (slashedProtocol[result.protocol] &&
          result.hostname && !result.pathname) {
        result.path = result.pathname = '/';
      }
  
      result.href = result.format();
      return result;
    }
  
    if (relative.protocol && relative.protocol !== result.protocol) {
      // if it's a known url protocol, then changing
      // the protocol does weird things
      // first, if it's not file:, then we MUST have a host,
      // and if there was a path
      // to begin with, then we MUST have a path.
      // if it is file:, then the host is dropped,
      // because that's known to be hostless.
      // anything else is assumed to be absolute.
      if (!slashedProtocol[relative.protocol]) {
        var keys = Object.keys(relative);
        for (var v = 0; v < keys.length; v++) {
          var k = keys[v];
          result[k] = relative[k];
        }
        result.href = result.format();
        return result;
      }
  
      result.protocol = relative.protocol;
      if (!relative.host && !hostlessProtocol[relative.protocol]) {
        var relPath = (relative.pathname || '').split('/');
        while (relPath.length && !(relative.host = relPath.shift()));
        if (!relative.host) relative.host = '';
        if (!relative.hostname) relative.hostname = '';
        if (relPath[0] !== '') relPath.unshift('');
        if (relPath.length < 2) relPath.unshift('');
        result.pathname = relPath.join('/');
      } else {
        result.pathname = relative.pathname;
      }
      result.search = relative.search;
      result.query = relative.query;
      result.host = relative.host || '';
      result.auth = relative.auth;
      result.hostname = relative.hostname || relative.host;
      result.port = relative.port;
      // to support http.request
      if (result.pathname || result.search) {
        var p = result.pathname || '';
        var s = result.search || '';
        result.path = p + s;
      }
      result.slashes = result.slashes || relative.slashes;
      result.href = result.format();
      return result;
    }
  
    var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'),
        isRelAbs = (
            relative.host ||
            relative.pathname && relative.pathname.charAt(0) === '/'
        ),
        mustEndAbs = (isRelAbs || isSourceAbs ||
                      (result.host && relative.pathname)),
        removeAllDots = mustEndAbs,
        srcPath = result.pathname && result.pathname.split('/') || [],
        relPath = relative.pathname && relative.pathname.split('/') || [],
        psychotic = result.protocol && !slashedProtocol[result.protocol];
  
    // if the url is a non-slashed url, then relative
    // links like ../.. should be able
    // to crawl up to the hostname, as well.  This is strange.
    // result.protocol has already been set by now.
    // Later on, put the first path part into the host field.
    if (psychotic) {
      result.hostname = '';
      result.port = null;
      if (result.host) {
        if (srcPath[0] === '') srcPath[0] = result.host;
        else srcPath.unshift(result.host);
      }
      result.host = '';
      if (relative.protocol) {
        relative.hostname = null;
        relative.port = null;
        if (relative.host) {
          if (relPath[0] === '') relPath[0] = relative.host;
          else relPath.unshift(relative.host);
        }
        relative.host = null;
      }
      mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === '');
    }
  
    if (isRelAbs) {
      // it's absolute.
      result.host = (relative.host || relative.host === '') ?
                    relative.host : result.host;
      result.hostname = (relative.hostname || relative.hostname === '') ?
                        relative.hostname : result.hostname;
      result.search = relative.search;
      result.query = relative.query;
      srcPath = relPath;
      // fall through to the dot-handling below.
    } else if (relPath.length) {
      // it's relative
      // throw away the existing file, and take the new path instead.
      if (!srcPath) srcPath = [];
      srcPath.pop();
      srcPath = srcPath.concat(relPath);
      result.search = relative.search;
      result.query = relative.query;
    } else if (!util.isNullOrUndefined(relative.search)) {
      // just pull out the search.
      // like href='?foo'.
      // Put this after the other two cases because it simplifies the booleans
      if (psychotic) {
        result.hostname = result.host = srcPath.shift();
        //occationaly the auth can get stuck only in host
        //this especially happens in cases like
        //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
        var authInHost = result.host && result.host.indexOf('@') > 0 ?
                         result.host.split('@') : false;
        if (authInHost) {
          result.auth = authInHost.shift();
          result.host = result.hostname = authInHost.shift();
        }
      }
      result.search = relative.search;
      result.query = relative.query;
      //to support http.request
      if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
        result.path = (result.pathname ? result.pathname : '') +
                      (result.search ? result.search : '');
      }
      result.href = result.format();
      return result;
    }
  
    if (!srcPath.length) {
      // no path at all.  easy.
      // we've already handled the other stuff above.
      result.pathname = null;
      //to support http.request
      if (result.search) {
        result.path = '/' + result.search;
      } else {
        result.path = null;
      }
      result.href = result.format();
      return result;
    }
  
    // if a url ENDs in . or .., then it must get a trailing slash.
    // however, if it ends in anything else non-slashy,
    // then it must NOT get a trailing slash.
    var last = srcPath.slice(-1)[0];
    var hasTrailingSlash = (
        (result.host || relative.host || srcPath.length > 1) &&
        (last === '.' || last === '..') || last === '');
  
    // strip single dots, resolve double dots to parent dir
    // if the path tries to go above the root, `up` ends up > 0
    var up = 0;
    for (var i = srcPath.length; i >= 0; i--) {
      last = srcPath[i];
      if (last === '.') {
        srcPath.splice(i, 1);
      } else if (last === '..') {
        srcPath.splice(i, 1);
        up++;
      } else if (up) {
        srcPath.splice(i, 1);
        up--;
      }
    }
  
    // if the path is allowed to go above the root, restore leading ..s
    if (!mustEndAbs && !removeAllDots) {
      for (; up--; up) {
        srcPath.unshift('..');
      }
    }
  
    if (mustEndAbs && srcPath[0] !== '' &&
        (!srcPath[0] || srcPath[0].charAt(0) !== '/')) {
      srcPath.unshift('');
    }
  
    if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {
      srcPath.push('');
    }
  
    var isAbsolute = srcPath[0] === '' ||
        (srcPath[0] && srcPath[0].charAt(0) === '/');
  
    // put the host back
    if (psychotic) {
      result.hostname = result.host = isAbsolute ? '' :
                                      srcPath.length ? srcPath.shift() : '';
      //occationaly the auth can get stuck only in host
      //this especially happens in cases like
      //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
      var authInHost = result.host && result.host.indexOf('@') > 0 ?
                       result.host.split('@') : false;
      if (authInHost) {
        result.auth = authInHost.shift();
        result.host = result.hostname = authInHost.shift();
      }
    }
  
    mustEndAbs = mustEndAbs || (result.host && srcPath.length);
  
    if (mustEndAbs && !isAbsolute) {
      srcPath.unshift('');
    }
  
    if (!srcPath.length) {
      result.pathname = null;
      result.path = null;
    } else {
      result.pathname = srcPath.join('/');
    }
  
    //to support request.http
    if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
      result.path = (result.pathname ? result.pathname : '') +
                    (result.search ? result.search : '');
    }
    result.auth = relative.auth || result.auth;
    result.slashes = result.slashes || relative.slashes;
    result.href = result.format();
    return result;
  };
  
  Url.prototype.parseHost = function() {
    var host = this.host;
    var port = portPattern.exec(host);
    if (port) {
      port = port[0];
      if (port !== ':') {
        this.port = port.substr(1);
      }
      host = host.substr(0, host.length - port.length);
    }
    if (host) this.hostname = host;
  };
  
  },{"./util":52,"punycode":26,"querystring":29}],52:[function(require,module,exports){
  'use strict';
  
  module.exports = {
    isString: function(arg) {
      return typeof(arg) === 'string';
    },
    isObject: function(arg) {
      return typeof(arg) === 'object' && arg !== null;
    },
    isNull: function(arg) {
      return arg === null;
    },
    isNullOrUndefined: function(arg) {
      return arg == null;
    }
  };
  
  },{}],53:[function(require,module,exports){
  module.exports = function isBuffer(arg) {
    return arg && typeof arg === 'object'
      && typeof arg.copy === 'function'
      && typeof arg.fill === 'function'
      && typeof arg.readUInt8 === 'function';
  }
  },{}],54:[function(require,module,exports){
  (function (process,global){
  // 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
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // 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 formatRegExp = /%[sdj%]/g;
  exports.format = function(f) {
    if (!isString(f)) {
      var objects = [];
      for (var i = 0; i < arguments.length; i++) {
        objects.push(inspect(arguments[i]));
      }
      return objects.join(' ');
    }
  
    var i = 1;
    var args = arguments;
    var len = args.length;
    var str = String(f).replace(formatRegExp, function(x) {
      if (x === '%%') return '%';
      if (i >= len) return x;
      switch (x) {
        case '%s': return String(args[i++]);
        case '%d': return Number(args[i++]);
        case '%j':
          try {
            return JSON.stringify(args[i++]);
          } catch (_) {
            return '[Circular]';
          }
        default:
          return x;
      }
    });
    for (var x = args[i]; i < len; x = args[++i]) {
      if (isNull(x) || !isObject(x)) {
        str += ' ' + x;
      } else {
        str += ' ' + inspect(x);
      }
    }
    return str;
  };
  
  
  // Mark that a method should not be used.
  // Returns a modified function which warns once by default.
  // If --no-deprecation is set, then it is a no-op.
  exports.deprecate = function(fn, msg) {
    // Allow for deprecating things in the process of starting up.
    if (isUndefined(global.process)) {
      return function() {
        return exports.deprecate(fn, msg).apply(this, arguments);
      };
    }
  
    if (process.noDeprecation === true) {
      return fn;
    }
  
    var warned = false;
    function deprecated() {
      if (!warned) {
        if (process.throwDeprecation) {
          throw new Error(msg);
        } else if (process.traceDeprecation) {
          console.trace(msg);
        } else {
          console.error(msg);
        }
        warned = true;
      }
      return fn.apply(this, arguments);
    }
  
    return deprecated;
  };
  
  
  var debugs = {};
  var debugEnviron;
  exports.debuglog = function(set) {
    if (isUndefined(debugEnviron))
      debugEnviron = process.env.NODE_DEBUG || '';
    set = set.toUpperCase();
    if (!debugs[set]) {
      if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
        var pid = process.pid;
        debugs[set] = function() {
          var msg = exports.format.apply(exports, arguments);
          console.error('%s %d: %s', set, pid, msg);
        };
      } else {
        debugs[set] = function() {};
      }
    }
    return debugs[set];
  };
  
  
  /**
   * Echos the value of a value. Trys to print the value out
   * in the best way possible given the different types.
   *
   * @param {Object} obj The object to print out.
   * @param {Object} opts Optional options object that alters the output.
   */
  /* legacy: obj, showHidden, depth, colors*/
  function inspect(obj, opts) {
    // default options
    var ctx = {
      seen: [],
      stylize: stylizeNoColor
    };
    // legacy...
    if (arguments.length >= 3) ctx.depth = arguments[2];
    if (arguments.length >= 4) ctx.colors = arguments[3];
    if (isBoolean(opts)) {
      // legacy...
      ctx.showHidden = opts;
    } else if (opts) {
      // got an "options" object
      exports._extend(ctx, opts);
    }
    // set default options
    if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
    if (isUndefined(ctx.depth)) ctx.depth = 2;
    if (isUndefined(ctx.colors)) ctx.colors = false;
    if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
    if (ctx.colors) ctx.stylize = stylizeWithColor;
    return formatValue(ctx, obj, ctx.depth);
  }
  exports.inspect = inspect;
  
  
  // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
  inspect.colors = {
    'bold' : [1, 22],
    'italic' : [3, 23],
    'underline' : [4, 24],
    'inverse' : [7, 27],
    'white' : [37, 39],
    'grey' : [90, 39],
    'black' : [30, 39],
    'blue' : [34, 39],
    'cyan' : [36, 39],
    'green' : [32, 39],
    'magenta' : [35, 39],
    'red' : [31, 39],
    'yellow' : [33, 39]
  };
  
  // Don't use 'blue' not visible on cmd.exe
  inspect.styles = {
    'special': 'cyan',
    'number': 'yellow',
    'boolean': 'yellow',
    'undefined': 'grey',
    'null': 'bold',
    'string': 'green',
    'date': 'magenta',
    // "name": intentionally not styling
    'regexp': 'red'
  };
  
  
  function stylizeWithColor(str, styleType) {
    var style = inspect.styles[styleType];
  
    if (style) {
      return '\u001b[' + inspect.colors[style][0] + 'm' + str +
             '\u001b[' + inspect.colors[style][1] + 'm';
    } else {
      return str;
    }
  }
  
  
  function stylizeNoColor(str, styleType) {
    return str;
  }
  
  
  function arrayToHash(array) {
    var hash = {};
  
    array.forEach(function(val, idx) {
      hash[val] = true;
    });
  
    return hash;
  }
  
  
  function formatValue(ctx, value, recurseTimes) {
    // Provide a hook for user-specified inspect functions.
    // Check that value is an object with an inspect function on it
    if (ctx.customInspect &&
        value &&
        isFunction(value.inspect) &&
        // Filter out the util module, it's inspect function is special
        value.inspect !== exports.inspect &&
        // Also filter out any prototype objects using the circular check.
        !(value.constructor && value.constructor.prototype === value)) {
      var ret = value.inspect(recurseTimes, ctx);
      if (!isString(ret)) {
        ret = formatValue(ctx, ret, recurseTimes);
      }
      return ret;
    }
  
    // Primitive types cannot have properties
    var primitive = formatPrimitive(ctx, value);
    if (primitive) {
      return primitive;
    }
  
    // Look up the keys of the object.
    var keys = Object.keys(value);
    var visibleKeys = arrayToHash(keys);
  
    if (ctx.showHidden) {
      keys = Object.getOwnPropertyNames(value);
    }
  
    // IE doesn't make error fields non-enumerable
    // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
    if (isError(value)
        && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
      return formatError(value);
    }
  
    // Some type of object without properties can be shortcutted.
    if (keys.length === 0) {
      if (isFunction(value)) {
        var name = value.name ? ': ' + value.name : '';
        return ctx.stylize('[Function' + name + ']', 'special');
      }
      if (isRegExp(value)) {
        return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
      }
      if (isDate(value)) {
        return ctx.stylize(Date.prototype.toString.call(value), 'date');
      }
      if (isError(value)) {
        return formatError(value);
      }
    }
  
    var base = '', array = false, braces = ['{', '}'];
  
    // Make Array say that they are Array
    if (isArray(value)) {
      array = true;
      braces = ['[', ']'];
    }
  
    // Make functions say that they are functions
    if (isFunction(value)) {
      var n = value.name ? ': ' + value.name : '';
      base = ' [Function' + n + ']';
    }
  
    // Make RegExps say that they are RegExps
    if (isRegExp(value)) {
      base = ' ' + RegExp.prototype.toString.call(value);
    }
  
    // Make dates with properties first say the date
    if (isDate(value)) {
      base = ' ' + Date.prototype.toUTCString.call(value);
    }
  
    // Make error with message first say the error
    if (isError(value)) {
      base = ' ' + formatError(value);
    }
  
    if (keys.length === 0 && (!array || value.length == 0)) {
      return braces[0] + base + braces[1];
    }
  
    if (recurseTimes < 0) {
      if (isRegExp(value)) {
        return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
      } else {
        return ctx.stylize('[Object]', 'special');
      }
    }
  
    ctx.seen.push(value);
  
    var output;
    if (array) {
      output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
    } else {
      output = keys.map(function(key) {
        return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
      });
    }
  
    ctx.seen.pop();
  
    return reduceToSingleString(output, base, braces);
  }
  
  
  function formatPrimitive(ctx, value) {
    if (isUndefined(value))
      return ctx.stylize('undefined', 'undefined');
    if (isString(value)) {
      var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
                                               .replace(/'/g, "\\'")
                                               .replace(/\\"/g, '"') + '\'';
      return ctx.stylize(simple, 'string');
    }
    if (isNumber(value))
      return ctx.stylize('' + value, 'number');
    if (isBoolean(value))
      return ctx.stylize('' + value, 'boolean');
    // For some reason typeof null is "object", so special case here.
    if (isNull(value))
      return ctx.stylize('null', 'null');
  }
  
  
  function formatError(value) {
    return '[' + Error.prototype.toString.call(value) + ']';
  }
  
  
  function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
    var output = [];
    for (var i = 0, l = value.length; i < l; ++i) {
      if (hasOwnProperty(value, String(i))) {
        output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
            String(i), true));
      } else {
        output.push('');
      }
    }
    keys.forEach(function(key) {
      if (!key.match(/^\d+$/)) {
        output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
            key, true));
      }
    });
    return output;
  }
  
  
  function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
    var name, str, desc;
    desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
    if (desc.get) {
      if (desc.set) {
        str = ctx.stylize('[Getter/Setter]', 'special');
      } else {
        str = ctx.stylize('[Getter]', 'special');
      }
    } else {
      if (desc.set) {
        str = ctx.stylize('[Setter]', 'special');
      }
    }
    if (!hasOwnProperty(visibleKeys, key)) {
      name = '[' + key + ']';
    }
    if (!str) {
      if (ctx.seen.indexOf(desc.value) < 0) {
        if (isNull(recurseTimes)) {
          str = formatValue(ctx, desc.value, null);
        } else {
          str = formatValue(ctx, desc.value, recurseTimes - 1);
        }
        if (str.indexOf('\n') > -1) {
          if (array) {
            str = str.split('\n').map(function(line) {
              return '  ' + line;
            }).join('\n').substr(2);
          } else {
            str = '\n' + str.split('\n').map(function(line) {
              return '   ' + line;
            }).join('\n');
          }
        }
      } else {
        str = ctx.stylize('[Circular]', 'special');
      }
    }
    if (isUndefined(name)) {
      if (array && key.match(/^\d+$/)) {
        return str;
      }
      name = JSON.stringify('' + key);
      if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
        name = name.substr(1, name.length - 2);
        name = ctx.stylize(name, 'name');
      } else {
        name = name.replace(/'/g, "\\'")
                   .replace(/\\"/g, '"')
                   .replace(/(^"|"$)/g, "'");
        name = ctx.stylize(name, 'string');
      }
    }
  
    return name + ': ' + str;
  }
  
  
  function reduceToSingleString(output, base, braces) {
    var numLinesEst = 0;
    var length = output.reduce(function(prev, cur) {
      numLinesEst++;
      if (cur.indexOf('\n') >= 0) numLinesEst++;
      return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
    }, 0);
  
    if (length > 60) {
      return braces[0] +
             (base === '' ? '' : base + '\n ') +
             ' ' +
             output.join(',\n  ') +
             ' ' +
             braces[1];
    }
  
    return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
  }
  
  
  // NOTE: These type checking functions intentionally don't use `instanceof`
  // because it is fragile and can be easily faked with `Object.create()`.
  function isArray(ar) {
    return Array.isArray(ar);
  }
  exports.isArray = isArray;
  
  function isBoolean(arg) {
    return typeof arg === 'boolean';
  }
  exports.isBoolean = isBoolean;
  
  function isNull(arg) {
    return arg === null;
  }
  exports.isNull = isNull;
  
  function isNullOrUndefined(arg) {
    return arg == null;
  }
  exports.isNullOrUndefined = isNullOrUndefined;
  
  function isNumber(arg) {
    return typeof arg === 'number';
  }
  exports.isNumber = isNumber;
  
  function isString(arg) {
    return typeof arg === 'string';
  }
  exports.isString = isString;
  
  function isSymbol(arg) {
    return typeof arg === 'symbol';
  }
  exports.isSymbol = isSymbol;
  
  function isUndefined(arg) {
    return arg === void 0;
  }
  exports.isUndefined = isUndefined;
  
  function isRegExp(re) {
    return isObject(re) && objectToString(re) === '[object RegExp]';
  }
  exports.isRegExp = isRegExp;
  
  function isObject(arg) {
    return typeof arg === 'object' && arg !== null;
  }
  exports.isObject = isObject;
  
  function isDate(d) {
    return isObject(d) && objectToString(d) === '[object Date]';
  }
  exports.isDate = isDate;
  
  function isError(e) {
    return isObject(e) &&
        (objectToString(e) === '[object Error]' || e instanceof Error);
  }
  exports.isError = isError;
  
  function isFunction(arg) {
    return typeof arg === 'function';
  }
  exports.isFunction = isFunction;
  
  function isPrimitive(arg) {
    return arg === null ||
           typeof arg === 'boolean' ||
           typeof arg === 'number' ||
           typeof arg === 'string' ||
           typeof arg === 'symbol' ||  // ES6 symbol
           typeof arg === 'undefined';
  }
  exports.isPrimitive = isPrimitive;
  
  exports.isBuffer = require('./support/isBuffer');
  
  function objectToString(o) {
    return Object.prototype.toString.call(o);
  }
  
  
  function pad(n) {
    return n < 10 ? '0' + n.toString(10) : n.toString(10);
  }
  
  
  var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
                'Oct', 'Nov', 'Dec'];
  
  // 26 Feb 16:19:34
  function timestamp() {
    var d = new Date();
    var time = [pad(d.getHours()),
                pad(d.getMinutes()),
                pad(d.getSeconds())].join(':');
    return [d.getDate(), months[d.getMonth()], time].join(' ');
  }
  
  
  // log is just a thin wrapper to console.log that prepends a timestamp
  exports.log = function() {
    console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
  };
  
  
  /**
   * Inherit the prototype methods from one constructor into another.
   *
   * The Function.prototype.inherits from lang.js rewritten as a standalone
   * function (not on Function.prototype). NOTE: If this file is to be loaded
   * during bootstrapping this function needs to be rewritten using some native
   * functions as prototype setup using normal JavaScript does not work as
   * expected during bootstrapping (see mirror.js in r114903).
   *
   * @param {function} ctor Constructor function which needs to inherit the
   *     prototype.
   * @param {function} superCtor Constructor function to inherit prototype from.
   */
  exports.inherits = require('inherits');
  
  exports._extend = function(origin, add) {
    // Don't do anything if add isn't an object
    if (!add || !isObject(add)) return origin;
  
    var keys = Object.keys(add);
    var i = keys.length;
    while (i--) {
      origin[keys[i]] = add[keys[i]];
    }
    return origin;
  };
  
  function hasOwnProperty(obj, prop) {
    return Object.prototype.hasOwnProperty.call(obj, prop);
  }
  
  }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{"./support/isBuffer":53,"_process":25,"inherits":21}],55:[function(require,module,exports){
  module.exports = extend
  
  var hasOwnProperty = Object.prototype.hasOwnProperty;
  
  function extend() {
      var target = {}
  
      for (var i = 0; i < arguments.length; i++) {
          var source = arguments[i]
  
          for (var key in source) {
              if (hasOwnProperty.call(source, key)) {
                  target[key] = source[key]
              }
          }
      }
  
      return target
  }
  
  },{}],56:[function(require,module,exports){
  module.exports = require('./lib/chai');
  
  },{"./lib/chai":57}],57:[function(require,module,exports){
  /*!
   * chai
   * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  var used = []
    , exports = module.exports = {};
  
  /*!
   * Chai version
   */
  
  exports.version = '3.4.1';
  
  /*!
   * Assertion Error
   */
  
  exports.AssertionError = require('assertion-error');
  
  /*!
   * Utils for plugins (not exported)
   */
  
  var util = require('./chai/utils');
  
  /**
   * # .use(function)
   *
   * Provides a way to extend the internals of Chai
   *
   * @param {Function}
   * @returns {this} for chaining
   * @api public
   */
  
  exports.use = function (fn) {
    if (!~used.indexOf(fn)) {
      fn(this, util);
      used.push(fn);
    }
  
    return this;
  };
  
  /*!
   * Utility Functions
   */
  
  exports.util = util;
  
  /*!
   * Configuration
   */
  
  var config = require('./chai/config');
  exports.config = config;
  
  /*!
   * Primary `Assertion` prototype
   */
  
  var assertion = require('./chai/assertion');
  exports.use(assertion);
  
  /*!
   * Core Assertions
   */
  
  var core = require('./chai/core/assertions');
  exports.use(core);
  
  /*!
   * Expect interface
   */
  
  var expect = require('./chai/interface/expect');
  exports.use(expect);
  
  /*!
   * Should interface
   */
  
  var should = require('./chai/interface/should');
  exports.use(should);
  
  /*!
   * Assert interface
   */
  
  var assert = require('./chai/interface/assert');
  exports.use(assert);
  
  },{"./chai/assertion":58,"./chai/config":59,"./chai/core/assertions":60,"./chai/interface/assert":61,"./chai/interface/expect":62,"./chai/interface/should":63,"./chai/utils":77,"assertion-error":85}],58:[function(require,module,exports){
  /*!
   * chai
   * http://chaijs.com
   * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  var config = require('./config');
  
  module.exports = function (_chai, util) {
    /*!
     * Module dependencies.
     */
  
    var AssertionError = _chai.AssertionError
      , flag = util.flag;
  
    /*!
     * Module export.
     */
  
    _chai.Assertion = Assertion;
  
    /*!
     * Assertion Constructor
     *
     * Creates object for chaining.
     *
     * @api private
     */
  
    function Assertion (obj, msg, stack) {
      flag(this, 'ssfi', stack || arguments.callee);
      flag(this, 'object', obj);
      flag(this, 'message', msg);
    }
  
    Object.defineProperty(Assertion, 'includeStack', {
      get: function() {
        console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.');
        return config.includeStack;
      },
      set: function(value) {
        console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.');
        config.includeStack = value;
      }
    });
  
    Object.defineProperty(Assertion, 'showDiff', {
      get: function() {
        console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.');
        return config.showDiff;
      },
      set: function(value) {
        console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.');
        config.showDiff = value;
      }
    });
  
    Assertion.addProperty = function (name, fn) {
      util.addProperty(this.prototype, name, fn);
    };
  
    Assertion.addMethod = function (name, fn) {
      util.addMethod(this.prototype, name, fn);
    };
  
    Assertion.addChainableMethod = function (name, fn, chainingBehavior) {
      util.addChainableMethod(this.prototype, name, fn, chainingBehavior);
    };
  
    Assertion.overwriteProperty = function (name, fn) {
      util.overwriteProperty(this.prototype, name, fn);
    };
  
    Assertion.overwriteMethod = function (name, fn) {
      util.overwriteMethod(this.prototype, name, fn);
    };
  
    Assertion.overwriteChainableMethod = function (name, fn, chainingBehavior) {
      util.overwriteChainableMethod(this.prototype, name, fn, chainingBehavior);
    };
  
    /**
     * ### .assert(expression, message, negateMessage, expected, actual, showDiff)
     *
     * Executes an expression and check expectations. Throws AssertionError for reporting if test doesn't pass.
     *
     * @name assert
     * @param {Philosophical} expression to be tested
     * @param {String|Function} message or function that returns message to display if expression fails
     * @param {String|Function} negatedMessage or function that returns negatedMessage to display if negated expression fails
     * @param {Mixed} expected value (remember to check for negation)
     * @param {Mixed} actual (optional) will default to `this.obj`
     * @param {Boolean} showDiff (optional) when set to `true`, assert will display a diff in addition to the message if expression fails
     * @api private
     */
  
    Assertion.prototype.assert = function (expr, msg, negateMsg, expected, _actual, showDiff) {
      var ok = util.test(this, arguments);
      if (true !== showDiff) showDiff = false;
      if (true !== config.showDiff) showDiff = false;
  
      if (!ok) {
        var msg = util.getMessage(this, arguments)
          , actual = util.getActual(this, arguments);
        throw new AssertionError(msg, {
            actual: actual
          , expected: expected
          , showDiff: showDiff
        }, (config.includeStack) ? this.assert : flag(this, 'ssfi'));
      }
    };
  
    /*!
     * ### ._obj
     *
     * Quick reference to stored `actual` value for plugin developers.
     *
     * @api private
     */
  
    Object.defineProperty(Assertion.prototype, '_obj',
      { get: function () {
          return flag(this, 'object');
        }
      , set: function (val) {
          flag(this, 'object', val);
        }
    });
  };
  
  },{"./config":59}],59:[function(require,module,exports){
  module.exports = {
  
    /**
     * ### config.includeStack
     *
     * User configurable property, influences whether stack trace
     * is included in Assertion error message. Default of false
     * suppresses stack trace in the error message.
     *
     *     chai.config.includeStack = true;  // enable stack on error
     *
     * @param {Boolean}
     * @api public
     */
  
     includeStack: false,
  
    /**
     * ### config.showDiff
     *
     * User configurable property, influences whether or not
     * the `showDiff` flag should be included in the thrown
     * AssertionErrors. `false` will always be `false`; `true`
     * will be true when the assertion has requested a diff
     * be shown.
     *
     * @param {Boolean}
     * @api public
     */
  
    showDiff: true,
  
    /**
     * ### config.truncateThreshold
     *
     * User configurable property, sets length threshold for actual and
     * expected values in assertion errors. If this threshold is exceeded, for
     * example for large data structures, the value is replaced with something
     * like `[ Array(3) ]` or `{ Object (prop1, prop2) }`.
     *
     * Set it to zero if you want to disable truncating altogether.
     *
     * This is especially userful when doing assertions on arrays: having this
     * set to a reasonable large value makes the failure messages readily
     * inspectable.
     *
     *     chai.config.truncateThreshold = 0;  // disable truncating
     *
     * @param {Number}
     * @api public
     */
  
    truncateThreshold: 40
  
  };
  
  },{}],60:[function(require,module,exports){
  /*!
   * chai
   * http://chaijs.com
   * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  module.exports = function (chai, _) {
    var Assertion = chai.Assertion
      , toString = Object.prototype.toString
      , flag = _.flag;
  
    /**
     * ### Language Chains
     *
     * The following are provided as chainable getters to
     * improve the readability of your assertions. They
     * do not provide testing capabilities unless they
     * have been overwritten by a plugin.
     *
     * **Chains**
     *
     * - to
     * - be
     * - been
     * - is
     * - that
     * - which
     * - and
     * - has
     * - have
     * - with
     * - at
     * - of
     * - same
     *
     * @name language chains
     * @api public
     */
  
    [ 'to', 'be', 'been'
    , 'is', 'and', 'has', 'have'
    , 'with', 'that', 'which', 'at'
    , 'of', 'same' ].forEach(function (chain) {
      Assertion.addProperty(chain, function () {
        return this;
      });
    });
  
    /**
     * ### .not
     *
     * Negates any of assertions following in the chain.
     *
     *     expect(foo).to.not.equal('bar');
     *     expect(goodFn).to.not.throw(Error);
     *     expect({ foo: 'baz' }).to.have.property('foo')
     *       .and.not.equal('bar');
     *
     * @name not
     * @api public
     */
  
    Assertion.addProperty('not', function () {
      flag(this, 'negate', true);
    });
  
    /**
     * ### .deep
     *
     * Sets the `deep` flag, later used by the `equal` and
     * `property` assertions.
     *
     *     expect(foo).to.deep.equal({ bar: 'baz' });
     *     expect({ foo: { bar: { baz: 'quux' } } })
     *       .to.have.deep.property('foo.bar.baz', 'quux');
     *
     * `.deep.property` special characters can be escaped
     * by adding two slashes before the `.` or `[]`.
     *
     *     var deepCss = { '.link': { '[target]': 42 }};
     *     expect(deepCss).to.have.deep.property('\\.link.\\[target\\]', 42);
     *
     * @name deep
     * @api public
     */
  
    Assertion.addProperty('deep', function () {
      flag(this, 'deep', true);
    });
  
    /**
     * ### .any
     *
     * Sets the `any` flag, (opposite of the `all` flag)
     * later used in the `keys` assertion.
     *
     *     expect(foo).to.have.any.keys('bar', 'baz');
     *
     * @name any
     * @api public
     */
  
    Assertion.addProperty('any', function () {
      flag(this, 'any', true);
      flag(this, 'all', false)
    });
  
  
    /**
     * ### .all
     *
     * Sets the `all` flag (opposite of the `any` flag)
     * later used by the `keys` assertion.
     *
     *     expect(foo).to.have.all.keys('bar', 'baz');
     *
     * @name all
     * @api public
     */
  
    Assertion.addProperty('all', function () {
      flag(this, 'all', true);
      flag(this, 'any', false);
    });
  
    /**
     * ### .a(type)
     *
     * The `a` and `an` assertions are aliases that can be
     * used either as language chains or to assert a value's
     * type.
     *
     *     // typeof
     *     expect('test').to.be.a('string');
     *     expect({ foo: 'bar' }).to.be.an('object');
     *     expect(null).to.be.a('null');
     *     expect(undefined).to.be.an('undefined');
     *     expect(new Error).to.be.an('error');
     *     expect(new Promise).to.be.a('promise');
     *     expect(new Float32Array()).to.be.a('float32array');
     *     expect(Symbol()).to.be.a('symbol');
     *
     *     // es6 overrides
     *     expect({[Symbol.toStringTag]:()=>'foo'}).to.be.a('foo');
     *
     *     // language chain
     *     expect(foo).to.be.an.instanceof(Foo);
     *
     * @name a
     * @alias an
     * @param {String} type
     * @param {String} message _optional_
     * @api public
     */
  
    function an (type, msg) {
      if (msg) flag(this, 'message', msg);
      type = type.toLowerCase();
      var obj = flag(this, 'object')
        , article = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(type.charAt(0)) ? 'an ' : 'a ';
  
      this.assert(
          type === _.type(obj)
        , 'expected #{this} to be ' + article + type
        , 'expected #{this} not to be ' + article + type
      );
    }
  
    Assertion.addChainableMethod('an', an);
    Assertion.addChainableMethod('a', an);
  
    /**
     * ### .include(value)
     *
     * The `include` and `contain` assertions can be used as either property
     * based language chains or as methods to assert the inclusion of an object
     * in an array or a substring in a string. When used as language chains,
     * they toggle the `contains` flag for the `keys` assertion.
     *
     *     expect([1,2,3]).to.include(2);
     *     expect('foobar').to.contain('foo');
     *     expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo');
     *
     * @name include
     * @alias contain
     * @alias includes
     * @alias contains
     * @param {Object|String|Number} obj
     * @param {String} message _optional_
     * @api public
     */
  
    function includeChainingBehavior () {
      flag(this, 'contains', true);
    }
  
    function include (val, msg) {
      _.expectTypes(this, ['array', 'object', 'string']);
  
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      var expected = false;
  
      if (_.type(obj) === 'array' && _.type(val) === 'object') {
        for (var i in obj) {
          if (_.eql(obj[i], val)) {
            expected = true;
            break;
          }
        }
      } else if (_.type(val) === 'object') {
        if (!flag(this, 'negate')) {
          for (var k in val) new Assertion(obj).property(k, val[k]);
          return;
        }
        var subset = {};
        for (var k in val) subset[k] = obj[k];
        expected = _.eql(subset, val);
      } else {
        expected = (obj != undefined) && ~obj.indexOf(val);
      }
      this.assert(
          expected
        , 'expected #{this} to include ' + _.inspect(val)
        , 'expected #{this} to not include ' + _.inspect(val));
    }
  
    Assertion.addChainableMethod('include', include, includeChainingBehavior);
    Assertion.addChainableMethod('contain', include, includeChainingBehavior);
    Assertion.addChainableMethod('contains', include, includeChainingBehavior);
    Assertion.addChainableMethod('includes', include, includeChainingBehavior);
  
    /**
     * ### .ok
     *
     * Asserts that the target is truthy.
     *
     *     expect('everything').to.be.ok;
     *     expect(1).to.be.ok;
     *     expect(false).to.not.be.ok;
     *     expect(undefined).to.not.be.ok;
     *     expect(null).to.not.be.ok;
     *
     * @name ok
     * @api public
     */
  
    Assertion.addProperty('ok', function () {
      this.assert(
          flag(this, 'object')
        , 'expected #{this} to be truthy'
        , 'expected #{this} to be falsy');
    });
  
    /**
     * ### .true
     *
     * Asserts that the target is `true`.
     *
     *     expect(true).to.be.true;
     *     expect(1).to.not.be.true;
     *
     * @name true
     * @api public
     */
  
    Assertion.addProperty('true', function () {
      this.assert(
          true === flag(this, 'object')
        , 'expected #{this} to be true'
        , 'expected #{this} to be false'
        , this.negate ? false : true
      );
    });
  
    /**
     * ### .false
     *
     * Asserts that the target is `false`.
     *
     *     expect(false).to.be.false;
     *     expect(0).to.not.be.false;
     *
     * @name false
     * @api public
     */
  
    Assertion.addProperty('false', function () {
      this.assert(
          false === flag(this, 'object')
        , 'expected #{this} to be false'
        , 'expected #{this} to be true'
        , this.negate ? true : false
      );
    });
  
    /**
     * ### .null
     *
     * Asserts that the target is `null`.
     *
     *     expect(null).to.be.null;
     *     expect(undefined).to.not.be.null;
     *
     * @name null
     * @api public
     */
  
    Assertion.addProperty('null', function () {
      this.assert(
          null === flag(this, 'object')
        , 'expected #{this} to be null'
        , 'expected #{this} not to be null'
      );
    });
  
    /**
     * ### .undefined
     *
     * Asserts that the target is `undefined`.
     *
     *     expect(undefined).to.be.undefined;
     *     expect(null).to.not.be.undefined;
     *
     * @name undefined
     * @api public
     */
  
    Assertion.addProperty('undefined', function () {
      this.assert(
          undefined === flag(this, 'object')
        , 'expected #{this} to be undefined'
        , 'expected #{this} not to be undefined'
      );
    });
  
    /**
     * ### .NaN
     * Asserts that the target is `NaN`.
     *
     *     expect('foo').to.be.NaN;
     *     expect(4).not.to.be.NaN;
     *
     * @name NaN
     * @api public
     */
  
    Assertion.addProperty('NaN', function () {
      this.assert(
          isNaN(flag(this, 'object'))
          , 'expected #{this} to be NaN'
          , 'expected #{this} not to be NaN'
      );
    });
  
    /**
     * ### .exist
     *
     * Asserts that the target is neither `null` nor `undefined`.
     *
     *     var foo = 'hi'
     *       , bar = null
     *       , baz;
     *
     *     expect(foo).to.exist;
     *     expect(bar).to.not.exist;
     *     expect(baz).to.not.exist;
     *
     * @name exist
     * @api public
     */
  
    Assertion.addProperty('exist', function () {
      this.assert(
          null != flag(this, 'object')
        , 'expected #{this} to exist'
        , 'expected #{this} to not exist'
      );
    });
  
  
    /**
     * ### .empty
     *
     * Asserts that the target's length is `0`. For arrays and strings, it checks
     * the `length` property. For objects, it gets the count of
     * enumerable keys.
     *
     *     expect([]).to.be.empty;
     *     expect('').to.be.empty;
     *     expect({}).to.be.empty;
     *
     * @name empty
     * @api public
     */
  
    Assertion.addProperty('empty', function () {
      var obj = flag(this, 'object')
        , expected = obj;
  
      if (Array.isArray(obj) || 'string' === typeof object) {
        expected = obj.length;
      } else if (typeof obj === 'object') {
        expected = Object.keys(obj).length;
      }
  
      this.assert(
          !expected
        , 'expected #{this} to be empty'
        , 'expected #{this} not to be empty'
      );
    });
  
    /**
     * ### .arguments
     *
     * Asserts that the target is an arguments object.
     *
     *     function test () {
     *       expect(arguments).to.be.arguments;
     *     }
     *
     * @name arguments
     * @alias Arguments
     * @api public
     */
  
    function checkArguments () {
      var obj = flag(this, 'object')
        , type = Object.prototype.toString.call(obj);
      this.assert(
          '[object Arguments]' === type
        , 'expected #{this} to be arguments but got ' + type
        , 'expected #{this} to not be arguments'
      );
    }
  
    Assertion.addProperty('arguments', checkArguments);
    Assertion.addProperty('Arguments', checkArguments);
  
    /**
     * ### .equal(value)
     *
     * Asserts that the target is strictly equal (`===`) to `value`.
     * Alternately, if the `deep` flag is set, asserts that
     * the target is deeply equal to `value`.
     *
     *     expect('hello').to.equal('hello');
     *     expect(42).to.equal(42);
     *     expect(1).to.not.equal(true);
     *     expect({ foo: 'bar' }).to.not.equal({ foo: 'bar' });
     *     expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' });
     *
     * @name equal
     * @alias equals
     * @alias eq
     * @alias deep.equal
     * @param {Mixed} value
     * @param {String} message _optional_
     * @api public
     */
  
    function assertEqual (val, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      if (flag(this, 'deep')) {
        return this.eql(val);
      } else {
        this.assert(
            val === obj
          , 'expected #{this} to equal #{exp}'
          , 'expected #{this} to not equal #{exp}'
          , val
          , this._obj
          , true
        );
      }
    }
  
    Assertion.addMethod('equal', assertEqual);
    Assertion.addMethod('equals', assertEqual);
    Assertion.addMethod('eq', assertEqual);
  
    /**
     * ### .eql(value)
     *
     * Asserts that the target is deeply equal to `value`.
     *
     *     expect({ foo: 'bar' }).to.eql({ foo: 'bar' });
     *     expect([ 1, 2, 3 ]).to.eql([ 1, 2, 3 ]);
     *
     * @name eql
     * @alias eqls
     * @param {Mixed} value
     * @param {String} message _optional_
     * @api public
     */
  
    function assertEql(obj, msg) {
      if (msg) flag(this, 'message', msg);
      this.assert(
          _.eql(obj, flag(this, 'object'))
        , 'expected #{this} to deeply equal #{exp}'
        , 'expected #{this} to not deeply equal #{exp}'
        , obj
        , this._obj
        , true
      );
    }
  
    Assertion.addMethod('eql', assertEql);
    Assertion.addMethod('eqls', assertEql);
  
    /**
     * ### .above(value)
     *
     * Asserts that the target is greater than `value`.
     *
     *     expect(10).to.be.above(5);
     *
     * Can also be used in conjunction with `length` to
     * assert a minimum length. The benefit being a
     * more informative error message than if the length
     * was supplied directly.
     *
     *     expect('foo').to.have.length.above(2);
     *     expect([ 1, 2, 3 ]).to.have.length.above(2);
     *
     * @name above
     * @alias gt
     * @alias greaterThan
     * @param {Number} value
     * @param {String} message _optional_
     * @api public
     */
  
    function assertAbove (n, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      if (flag(this, 'doLength')) {
        new Assertion(obj, msg).to.have.property('length');
        var len = obj.length;
        this.assert(
            len > n
          , 'expected #{this} to have a length above #{exp} but got #{act}'
          , 'expected #{this} to not have a length above #{exp}'
          , n
          , len
        );
      } else {
        this.assert(
            obj > n
          , 'expected #{this} to be above ' + n
          , 'expected #{this} to be at most ' + n
        );
      }
    }
  
    Assertion.addMethod('above', assertAbove);
    Assertion.addMethod('gt', assertAbove);
    Assertion.addMethod('greaterThan', assertAbove);
  
    /**
     * ### .least(value)
     *
     * Asserts that the target is greater than or equal to `value`.
     *
     *     expect(10).to.be.at.least(10);
     *
     * Can also be used in conjunction with `length` to
     * assert a minimum length. The benefit being a
     * more informative error message than if the length
     * was supplied directly.
     *
     *     expect('foo').to.have.length.of.at.least(2);
     *     expect([ 1, 2, 3 ]).to.have.length.of.at.least(3);
     *
     * @name least
     * @alias gte
     * @param {Number} value
     * @param {String} message _optional_
     * @api public
     */
  
    function assertLeast (n, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      if (flag(this, 'doLength')) {
        new Assertion(obj, msg).to.have.property('length');
        var len = obj.length;
        this.assert(
            len >= n
          , 'expected #{this} to have a length at least #{exp} but got #{act}'
          , 'expected #{this} to have a length below #{exp}'
          , n
          , len
        );
      } else {
        this.assert(
            obj >= n
          , 'expected #{this} to be at least ' + n
          , 'expected #{this} to be below ' + n
        );
      }
    }
  
    Assertion.addMethod('least', assertLeast);
    Assertion.addMethod('gte', assertLeast);
  
    /**
     * ### .below(value)
     *
     * Asserts that the target is less than `value`.
     *
     *     expect(5).to.be.below(10);
     *
     * Can also be used in conjunction with `length` to
     * assert a maximum length. The benefit being a
     * more informative error message than if the length
     * was supplied directly.
     *
     *     expect('foo').to.have.length.below(4);
     *     expect([ 1, 2, 3 ]).to.have.length.below(4);
     *
     * @name below
     * @alias lt
     * @alias lessThan
     * @param {Number} value
     * @param {String} message _optional_
     * @api public
     */
  
    function assertBelow (n, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      if (flag(this, 'doLength')) {
        new Assertion(obj, msg).to.have.property('length');
        var len = obj.length;
        this.assert(
            len < n
          , 'expected #{this} to have a length below #{exp} but got #{act}'
          , 'expected #{this} to not have a length below #{exp}'
          , n
          , len
        );
      } else {
        this.assert(
            obj < n
          , 'expected #{this} to be below ' + n
          , 'expected #{this} to be at least ' + n
        );
      }
    }
  
    Assertion.addMethod('below', assertBelow);
    Assertion.addMethod('lt', assertBelow);
    Assertion.addMethod('lessThan', assertBelow);
  
    /**
     * ### .most(value)
     *
     * Asserts that the target is less than or equal to `value`.
     *
     *     expect(5).to.be.at.most(5);
     *
     * Can also be used in conjunction with `length` to
     * assert a maximum length. The benefit being a
     * more informative error message than if the length
     * was supplied directly.
     *
     *     expect('foo').to.have.length.of.at.most(4);
     *     expect([ 1, 2, 3 ]).to.have.length.of.at.most(3);
     *
     * @name most
     * @alias lte
     * @param {Number} value
     * @param {String} message _optional_
     * @api public
     */
  
    function assertMost (n, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      if (flag(this, 'doLength')) {
        new Assertion(obj, msg).to.have.property('length');
        var len = obj.length;
        this.assert(
            len <= n
          , 'expected #{this} to have a length at most #{exp} but got #{act}'
          , 'expected #{this} to have a length above #{exp}'
          , n
          , len
        );
      } else {
        this.assert(
            obj <= n
          , 'expected #{this} to be at most ' + n
          , 'expected #{this} to be above ' + n
        );
      }
    }
  
    Assertion.addMethod('most', assertMost);
    Assertion.addMethod('lte', assertMost);
  
    /**
     * ### .within(start, finish)
     *
     * Asserts that the target is within a range.
     *
     *     expect(7).to.be.within(5,10);
     *
     * Can also be used in conjunction with `length` to
     * assert a length range. The benefit being a
     * more informative error message than if the length
     * was supplied directly.
     *
     *     expect('foo').to.have.length.within(2,4);
     *     expect([ 1, 2, 3 ]).to.have.length.within(2,4);
     *
     * @name within
     * @param {Number} start lowerbound inclusive
     * @param {Number} finish upperbound inclusive
     * @param {String} message _optional_
     * @api public
     */
  
    Assertion.addMethod('within', function (start, finish, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object')
        , range = start + '..' + finish;
      if (flag(this, 'doLength')) {
        new Assertion(obj, msg).to.have.property('length');
        var len = obj.length;
        this.assert(
            len >= start && len <= finish
          , 'expected #{this} to have a length within ' + range
          , 'expected #{this} to not have a length within ' + range
        );
      } else {
        this.assert(
            obj >= start && obj <= finish
          , 'expected #{this} to be within ' + range
          , 'expected #{this} to not be within ' + range
        );
      }
    });
  
    /**
     * ### .instanceof(constructor)
     *
     * Asserts that the target is an instance of `constructor`.
     *
     *     var Tea = function (name) { this.name = name; }
     *       , Chai = new Tea('chai');
     *
     *     expect(Chai).to.be.an.instanceof(Tea);
     *     expect([ 1, 2, 3 ]).to.be.instanceof(Array);
     *
     * @name instanceof
     * @param {Constructor} constructor
     * @param {String} message _optional_
     * @alias instanceOf
     * @api public
     */
  
    function assertInstanceOf (constructor, msg) {
      if (msg) flag(this, 'message', msg);
      var name = _.getName(constructor);
      this.assert(
          flag(this, 'object') instanceof constructor
        , 'expected #{this} to be an instance of ' + name
        , 'expected #{this} to not be an instance of ' + name
      );
    };
  
    Assertion.addMethod('instanceof', assertInstanceOf);
    Assertion.addMethod('instanceOf', assertInstanceOf);
  
    /**
     * ### .property(name, [value])
     *
     * Asserts that the target has a property `name`, optionally asserting that
     * the value of that property is strictly equal to  `value`.
     * If the `deep` flag is set, you can use dot- and bracket-notation for deep
     * references into objects and arrays.
     *
     *     // simple referencing
     *     var obj = { foo: 'bar' };
     *     expect(obj).to.have.property('foo');
     *     expect(obj).to.have.property('foo', 'bar');
     *
     *     // deep referencing
     *     var deepObj = {
     *         green: { tea: 'matcha' }
     *       , teas: [ 'chai', 'matcha', { tea: 'konacha' } ]
     *     };
     *
     *     expect(deepObj).to.have.deep.property('green.tea', 'matcha');
     *     expect(deepObj).to.have.deep.property('teas[1]', 'matcha');
     *     expect(deepObj).to.have.deep.property('teas[2].tea', 'konacha');
     *
     * You can also use an array as the starting point of a `deep.property`
     * assertion, or traverse nested arrays.
     *
     *     var arr = [
     *         [ 'chai', 'matcha', 'konacha' ]
     *       , [ { tea: 'chai' }
     *         , { tea: 'matcha' }
     *         , { tea: 'konacha' } ]
     *     ];
     *
     *     expect(arr).to.have.deep.property('[0][1]', 'matcha');
     *     expect(arr).to.have.deep.property('[1][2].tea', 'konacha');
     *
     * Furthermore, `property` changes the subject of the assertion
     * to be the value of that property from the original object. This
     * permits for further chainable assertions on that property.
     *
     *     expect(obj).to.have.property('foo')
     *       .that.is.a('string');
     *     expect(deepObj).to.have.property('green')
     *       .that.is.an('object')
     *       .that.deep.equals({ tea: 'matcha' });
     *     expect(deepObj).to.have.property('teas')
     *       .that.is.an('array')
     *       .with.deep.property('[2]')
     *         .that.deep.equals({ tea: 'konacha' });
     *
     * Note that dots and bracket in `name` must be backslash-escaped when
     * the `deep` flag is set, while they must NOT be escaped when the `deep`
     * flag is not set.
     *
     *     // simple referencing
     *     var css = { '.link[target]': 42 };
     *     expect(css).to.have.property('.link[target]', 42);
     *
     *     // deep referencing
     *     var deepCss = { '.link': { '[target]': 42 }};
     *     expect(deepCss).to.have.deep.property('\\.link.\\[target\\]', 42);
     *
     * @name property
     * @alias deep.property
     * @param {String} name
     * @param {Mixed} value (optional)
     * @param {String} message _optional_
     * @returns value of property for chaining
     * @api public
     */
  
    Assertion.addMethod('property', function (name, val, msg) {
      if (msg) flag(this, 'message', msg);
  
      var isDeep = !!flag(this, 'deep')
        , descriptor = isDeep ? 'deep property ' : 'property '
        , negate = flag(this, 'negate')
        , obj = flag(this, 'object')
        , pathInfo = isDeep ? _.getPathInfo(name, obj) : null
        , hasProperty = isDeep
          ? pathInfo.exists
          : _.hasProperty(name, obj)
        , value = isDeep
          ? pathInfo.value
          : obj[name];
  
      if (negate && arguments.length > 1) {
        if (undefined === value) {
          msg = (msg != null) ? msg + ': ' : '';
          throw new Error(msg + _.inspect(obj) + ' has no ' + descriptor + _.inspect(name));
        }
      } else {
        this.assert(
            hasProperty
          , 'expected #{this} to have a ' + descriptor + _.inspect(name)
          , 'expected #{this} to not have ' + descriptor + _.inspect(name));
      }
  
      if (arguments.length > 1) {
        this.assert(
            val === value
          , 'expected #{this} to have a ' + descriptor + _.inspect(name) + ' of #{exp}, but got #{act}'
          , 'expected #{this} to not have a ' + descriptor + _.inspect(name) + ' of #{act}'
          , val
          , value
        );
      }
  
      flag(this, 'object', value);
    });
  
  
    /**
     * ### .ownProperty(name)
     *
     * Asserts that the target has an own property `name`.
     *
     *     expect('test').to.have.ownProperty('length');
     *
     * @name ownProperty
     * @alias haveOwnProperty
     * @param {String} name
     * @param {String} message _optional_
     * @api public
     */
  
    function assertOwnProperty (name, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      this.assert(
          obj.hasOwnProperty(name)
        , 'expected #{this} to have own property ' + _.inspect(name)
        , 'expected #{this} to not have own property ' + _.inspect(name)
      );
    }
  
    Assertion.addMethod('ownProperty', assertOwnProperty);
    Assertion.addMethod('haveOwnProperty', assertOwnProperty);
  
    /**
     * ### .ownPropertyDescriptor(name[, descriptor[, message]])
     *
     * Asserts that the target has an own property descriptor `name`, that optionally matches `descriptor`.
     *
     *     expect('test').to.have.ownPropertyDescriptor('length');
     *     expect('test').to.have.ownPropertyDescriptor('length', { enumerable: false, configurable: false, writable: false, value: 4 });
     *     expect('test').not.to.have.ownPropertyDescriptor('length', { enumerable: false, configurable: false, writable: false, value: 3 });
     *     expect('test').ownPropertyDescriptor('length').to.have.property('enumerable', false);
     *     expect('test').ownPropertyDescriptor('length').to.have.keys('value');
     *
     * @name ownPropertyDescriptor
     * @alias haveOwnPropertyDescriptor
     * @param {String} name
     * @param {Object} descriptor _optional_
     * @param {String} message _optional_
     * @api public
     */
  
    function assertOwnPropertyDescriptor (name, descriptor, msg) {
      if (typeof descriptor === 'string') {
        msg = descriptor;
        descriptor = null;
      }
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      var actualDescriptor = Object.getOwnPropertyDescriptor(Object(obj), name);
      if (actualDescriptor && descriptor) {
        this.assert(
            _.eql(descriptor, actualDescriptor)
          , 'expected the own property descriptor for ' + _.inspect(name) + ' on #{this} to match ' + _.inspect(descriptor) + ', got ' + _.inspect(actualDescriptor)
          , 'expected the own property descriptor for ' + _.inspect(name) + ' on #{this} to not match ' + _.inspect(descriptor)
          , descriptor
          , actualDescriptor
          , true
        );
      } else {
        this.assert(
            actualDescriptor
          , 'expected #{this} to have an own property descriptor for ' + _.inspect(name)
          , 'expected #{this} to not have an own property descriptor for ' + _.inspect(name)
        );
      }
      flag(this, 'object', actualDescriptor);
    }
  
    Assertion.addMethod('ownPropertyDescriptor', assertOwnPropertyDescriptor);
    Assertion.addMethod('haveOwnPropertyDescriptor', assertOwnPropertyDescriptor);
  
    /**
     * ### .length
     *
     * Sets the `doLength` flag later used as a chain precursor to a value
     * comparison for the `length` property.
     *
     *     expect('foo').to.have.length.above(2);
     *     expect([ 1, 2, 3 ]).to.have.length.above(2);
     *     expect('foo').to.have.length.below(4);
     *     expect([ 1, 2, 3 ]).to.have.length.below(4);
     *     expect('foo').to.have.length.within(2,4);
     *     expect([ 1, 2, 3 ]).to.have.length.within(2,4);
     *
     * *Deprecation notice:* Using `length` as an assertion will be deprecated
     * in version 2.4.0 and removed in 3.0.0. Code using the old style of
     * asserting for `length` property value using `length(value)` should be
     * switched to use `lengthOf(value)` instead.
     *
     * @name length
     * @api public
     */
  
    /**
     * ### .lengthOf(value[, message])
     *
     * Asserts that the target's `length` property has
     * the expected value.
     *
     *     expect([ 1, 2, 3]).to.have.lengthOf(3);
     *     expect('foobar').to.have.lengthOf(6);
     *
     * @name lengthOf
     * @param {Number} length
     * @param {String} message _optional_
     * @api public
     */
  
    function assertLengthChain () {
      flag(this, 'doLength', true);
    }
  
    function assertLength (n, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      new Assertion(obj, msg).to.have.property('length');
      var len = obj.length;
  
      this.assert(
          len == n
        , 'expected #{this} to have a length of #{exp} but got #{act}'
        , 'expected #{this} to not have a length of #{act}'
        , n
        , len
      );
    }
  
    Assertion.addChainableMethod('length', assertLength, assertLengthChain);
    Assertion.addMethod('lengthOf', assertLength);
  
    /**
     * ### .match(regexp)
     *
     * Asserts that the target matches a regular expression.
     *
     *     expect('foobar').to.match(/^foo/);
     *
     * @name match
     * @alias matches
     * @param {RegExp} RegularExpression
     * @param {String} message _optional_
     * @api public
     */
    function assertMatch(re, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      this.assert(
          re.exec(obj)
        , 'expected #{this} to match ' + re
        , 'expected #{this} not to match ' + re
      );
    }
  
    Assertion.addMethod('match', assertMatch);
    Assertion.addMethod('matches', assertMatch);
  
    /**
     * ### .string(string)
     *
     * Asserts that the string target contains another string.
     *
     *     expect('foobar').to.have.string('bar');
     *
     * @name string
     * @param {String} string
     * @param {String} message _optional_
     * @api public
     */
  
    Assertion.addMethod('string', function (str, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      new Assertion(obj, msg).is.a('string');
  
      this.assert(
          ~obj.indexOf(str)
        , 'expected #{this} to contain ' + _.inspect(str)
        , 'expected #{this} to not contain ' + _.inspect(str)
      );
    });
  
  
    /**
     * ### .keys(key1, [key2], [...])
     *
     * Asserts that the target contains any or all of the passed-in keys.
     * Use in combination with `any`, `all`, `contains`, or `have` will affect
     * what will pass.
     *
     * When used in conjunction with `any`, at least one key that is passed
     * in must exist in the target object. This is regardless whether or not
     * the `have` or `contain` qualifiers are used. Note, either `any` or `all`
     * should be used in the assertion. If neither are used, the assertion is
     * defaulted to `all`.
     *
     * When both `all` and `contain` are used, the target object must have at
     * least all of the passed-in keys but may have more keys not listed.
     *
     * When both `all` and `have` are used, the target object must both contain
     * all of the passed-in keys AND the number of keys in the target object must
     * match the number of keys passed in (in other words, a target object must
     * have all and only all of the passed-in keys).
     *
     *     expect({ foo: 1, bar: 2 }).to.have.any.keys('foo', 'baz');
     *     expect({ foo: 1, bar: 2 }).to.have.any.keys('foo');
     *     expect({ foo: 1, bar: 2 }).to.contain.any.keys('bar', 'baz');
     *     expect({ foo: 1, bar: 2 }).to.contain.any.keys(['foo']);
     *     expect({ foo: 1, bar: 2 }).to.contain.any.keys({'foo': 6});
     *     expect({ foo: 1, bar: 2 }).to.have.all.keys(['bar', 'foo']);
     *     expect({ foo: 1, bar: 2 }).to.have.all.keys({'bar': 6, 'foo': 7});
     *     expect({ foo: 1, bar: 2, baz: 3 }).to.contain.all.keys(['bar', 'foo']);
     *     expect({ foo: 1, bar: 2, baz: 3 }).to.contain.all.keys({'bar': 6});
     *
     *
     * @name keys
     * @alias key
     * @param {...String|Array|Object} keys
     * @api public
     */
  
    function assertKeys (keys) {
      var obj = flag(this, 'object')
        , str
        , ok = true
        , mixedArgsMsg = 'keys must be given single argument of Array|Object|String, or multiple String arguments';
  
      switch (_.type(keys)) {
        case "array":
          if (arguments.length > 1) throw (new Error(mixedArgsMsg));
          break;
        case "object":
          if (arguments.length > 1) throw (new Error(mixedArgsMsg));
          keys = Object.keys(keys);
          break;
        default:
          keys = Array.prototype.slice.call(arguments);
      }
  
      if (!keys.length) throw new Error('keys required');
  
      var actual = Object.keys(obj)
        , expected = keys
        , len = keys.length
        , any = flag(this, 'any')
        , all = flag(this, 'all');
  
      if (!any && !all) {
        all = true;
      }
  
      // Has any
      if (any) {
        var intersection = expected.filter(function(key) {
          return ~actual.indexOf(key);
        });
        ok = intersection.length > 0;
      }
  
      // Has all
      if (all) {
        ok = keys.every(function(key){
          return ~actual.indexOf(key);
        });
        if (!flag(this, 'negate') && !flag(this, 'contains')) {
          ok = ok && keys.length == actual.length;
        }
      }
  
      // Key string
      if (len > 1) {
        keys = keys.map(function(key){
          return _.inspect(key);
        });
        var last = keys.pop();
        if (all) {
          str = keys.join(', ') + ', and ' + last;
        }
        if (any) {
          str = keys.join(', ') + ', or ' + last;
        }
      } else {
        str = _.inspect(keys[0]);
      }
  
      // Form
      str = (len > 1 ? 'keys ' : 'key ') + str;
  
      // Have / include
      str = (flag(this, 'contains') ? 'contain ' : 'have ') + str;
  
      // Assertion
      this.assert(
          ok
        , 'expected #{this} to ' + str
        , 'expected #{this} to not ' + str
        , expected.slice(0).sort()
        , actual.sort()
        , true
      );
    }
  
    Assertion.addMethod('keys', assertKeys);
    Assertion.addMethod('key', assertKeys);
  
    /**
     * ### .throw(constructor)
     *
     * Asserts that the function target will throw a specific error, or specific type of error
     * (as determined using `instanceof`), optionally with a RegExp or string inclusion test
     * for the error's message.
     *
     *     var err = new ReferenceError('This is a bad function.');
     *     var fn = function () { throw err; }
     *     expect(fn).to.throw(ReferenceError);
     *     expect(fn).to.throw(Error);
     *     expect(fn).to.throw(/bad function/);
     *     expect(fn).to.not.throw('good function');
     *     expect(fn).to.throw(ReferenceError, /bad function/);
     *     expect(fn).to.throw(err);
     *
     * Please note that when a throw expectation is negated, it will check each
     * parameter independently, starting with error constructor type. The appropriate way
     * to check for the existence of a type of error but for a message that does not match
     * is to use `and`.
     *
     *     expect(fn).to.throw(ReferenceError)
     *        .and.not.throw(/good function/);
     *
     * @name throw
     * @alias throws
     * @alias Throw
     * @param {ErrorConstructor} constructor
     * @param {String|RegExp} expected error message
     * @param {String} message _optional_
     * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
     * @returns error for chaining (null if no error)
     * @api public
     */
  
    function assertThrows (constructor, errMsg, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      new Assertion(obj, msg).is.a('function');
  
      var thrown = false
        , desiredError = null
        , name = null
        , thrownError = null;
  
      if (arguments.length === 0) {
        errMsg = null;
        constructor = null;
      } else if (constructor && (constructor instanceof RegExp || 'string' === typeof constructor)) {
        errMsg = constructor;
        constructor = null;
      } else if (constructor && constructor instanceof Error) {
        desiredError = constructor;
        constructor = null;
        errMsg = null;
      } else if (typeof constructor === 'function') {
        name = constructor.prototype.name;
        if (!name || (name === 'Error' && constructor !== Error)) {
          name = constructor.name || (new constructor()).name;
        }
      } else {
        constructor = null;
      }
  
      try {
        obj();
      } catch (err) {
        // first, check desired error
        if (desiredError) {
          this.assert(
              err === desiredError
            , 'expected #{this} to throw #{exp} but #{act} was thrown'
            , 'expected #{this} to not throw #{exp}'
            , (desiredError instanceof Error ? desiredError.toString() : desiredError)
            , (err instanceof Error ? err.toString() : err)
          );
  
          flag(this, 'object', err);
          return this;
        }
  
        // next, check constructor
        if (constructor) {
          this.assert(
              err instanceof constructor
            , 'expected #{this} to throw #{exp} but #{act} was thrown'
            , 'expected #{this} to not throw #{exp} but #{act} was thrown'
            , name
            , (err instanceof Error ? err.toString() : err)
          );
  
          if (!errMsg) {
            flag(this, 'object', err);
            return this;
          }
        }
  
        // next, check message
        var message = 'error' === _.type(err) && "message" in err
          ? err.message
          : '' + err;
  
        if ((message != null) && errMsg && errMsg instanceof RegExp) {
          this.assert(
              errMsg.exec(message)
            , 'expected #{this} to throw error matching #{exp} but got #{act}'
            , 'expected #{this} to throw error not matching #{exp}'
            , errMsg
            , message
          );
  
          flag(this, 'object', err);
          return this;
        } else if ((message != null) && errMsg && 'string' === typeof errMsg) {
          this.assert(
              ~message.indexOf(errMsg)
            , 'expected #{this} to throw error including #{exp} but got #{act}'
            , 'expected #{this} to throw error not including #{act}'
            , errMsg
            , message
          );
  
          flag(this, 'object', err);
          return this;
        } else {
          thrown = true;
          thrownError = err;
        }
      }
  
      var actuallyGot = ''
        , expectedThrown = name !== null
          ? name
          : desiredError
            ? '#{exp}' //_.inspect(desiredError)
            : 'an error';
  
      if (thrown) {
        actuallyGot = ' but #{act} was thrown'
      }
  
      this.assert(
          thrown === true
        , 'expected #{this} to throw ' + expectedThrown + actuallyGot
        , 'expected #{this} to not throw ' + expectedThrown + actuallyGot
        , (desiredError instanceof Error ? desiredError.toString() : desiredError)
        , (thrownError instanceof Error ? thrownError.toString() : thrownError)
      );
  
      flag(this, 'object', thrownError);
    };
  
    Assertion.addMethod('throw', assertThrows);
    Assertion.addMethod('throws', assertThrows);
    Assertion.addMethod('Throw', assertThrows);
  
    /**
     * ### .respondTo(method)
     *
     * Asserts that the object or class target will respond to a method.
     *
     *     Klass.prototype.bar = function(){};
     *     expect(Klass).to.respondTo('bar');
     *     expect(obj).to.respondTo('bar');
     *
     * To check if a constructor will respond to a static function,
     * set the `itself` flag.
     *
     *     Klass.baz = function(){};
     *     expect(Klass).itself.to.respondTo('baz');
     *
     * @name respondTo
     * @alias respondsTo
     * @param {String} method
     * @param {String} message _optional_
     * @api public
     */
  
    function respondTo (method, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object')
        , itself = flag(this, 'itself')
        , context = ('function' === _.type(obj) && !itself)
          ? obj.prototype[method]
          : obj[method];
  
      this.assert(
          'function' === typeof context
        , 'expected #{this} to respond to ' + _.inspect(method)
        , 'expected #{this} to not respond to ' + _.inspect(method)
      );
    }
  
    Assertion.addMethod('respondTo', respondTo);
    Assertion.addMethod('respondsTo', respondTo);
  
    /**
     * ### .itself
     *
     * Sets the `itself` flag, later used by the `respondTo` assertion.
     *
     *     function Foo() {}
     *     Foo.bar = function() {}
     *     Foo.prototype.baz = function() {}
     *
     *     expect(Foo).itself.to.respondTo('bar');
     *     expect(Foo).itself.not.to.respondTo('baz');
     *
     * @name itself
     * @api public
     */
  
    Assertion.addProperty('itself', function () {
      flag(this, 'itself', true);
    });
  
    /**
     * ### .satisfy(method)
     *
     * Asserts that the target passes a given truth test.
     *
     *     expect(1).to.satisfy(function(num) { return num > 0; });
     *
     * @name satisfy
     * @alias satisfies
     * @param {Function} matcher
     * @param {String} message _optional_
     * @api public
     */
  
    function satisfy (matcher, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      var result = matcher(obj);
      this.assert(
          result
        , 'expected #{this} to satisfy ' + _.objDisplay(matcher)
        , 'expected #{this} to not satisfy' + _.objDisplay(matcher)
        , this.negate ? false : true
        , result
      );
    }
  
    Assertion.addMethod('satisfy', satisfy);
    Assertion.addMethod('satisfies', satisfy);
  
    /**
     * ### .closeTo(expected, delta)
     *
     * Asserts that the target is equal `expected`, to within a +/- `delta` range.
     *
     *     expect(1.5).to.be.closeTo(1, 0.5);
     *
     * @name closeTo
     * @alias approximately
     * @param {Number} expected
     * @param {Number} delta
     * @param {String} message _optional_
     * @api public
     */
  
    function closeTo(expected, delta, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
  
      new Assertion(obj, msg).is.a('number');
      if (_.type(expected) !== 'number' || _.type(delta) !== 'number') {
        throw new Error('the arguments to closeTo or approximately must be numbers');
      }
  
      this.assert(
          Math.abs(obj - expected) <= delta
        , 'expected #{this} to be close to ' + expected + ' +/- ' + delta
        , 'expected #{this} not to be close to ' + expected + ' +/- ' + delta
      );
    }
  
    Assertion.addMethod('closeTo', closeTo);
    Assertion.addMethod('approximately', closeTo);
  
    function isSubsetOf(subset, superset, cmp) {
      return subset.every(function(elem) {
        if (!cmp) return superset.indexOf(elem) !== -1;
  
        return superset.some(function(elem2) {
          return cmp(elem, elem2);
        });
      })
    }
  
    /**
     * ### .members(set)
     *
     * Asserts that the target is a superset of `set`,
     * or that the target and `set` have the same strictly-equal (===) members.
     * Alternately, if the `deep` flag is set, set members are compared for deep
     * equality.
     *
     *     expect([1, 2, 3]).to.include.members([3, 2]);
     *     expect([1, 2, 3]).to.not.include.members([3, 2, 8]);
     *
     *     expect([4, 2]).to.have.members([2, 4]);
     *     expect([5, 2]).to.not.have.members([5, 2, 1]);
     *
     *     expect([{ id: 1 }]).to.deep.include.members([{ id: 1 }]);
     *
     * @name members
     * @param {Array} set
     * @param {String} message _optional_
     * @api public
     */
  
    Assertion.addMethod('members', function (subset, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
  
      new Assertion(obj).to.be.an('array');
      new Assertion(subset).to.be.an('array');
  
      var cmp = flag(this, 'deep') ? _.eql : undefined;
  
      if (flag(this, 'contains')) {
        return this.assert(
            isSubsetOf(subset, obj, cmp)
          , 'expected #{this} to be a superset of #{act}'
          , 'expected #{this} to not be a superset of #{act}'
          , obj
          , subset
        );
      }
  
      this.assert(
          isSubsetOf(obj, subset, cmp) && isSubsetOf(subset, obj, cmp)
          , 'expected #{this} to have the same members as #{act}'
          , 'expected #{this} to not have the same members as #{act}'
          , obj
          , subset
      );
    });
  
    /**
     * ### .oneOf(list)
     *
     * Assert that a value appears somewhere in the top level of array `list`.
     *
     *     expect('a').to.be.oneOf(['a', 'b', 'c']);
     *     expect(9).to.not.be.oneOf(['z']);
     *     expect([3]).to.not.be.oneOf([1, 2, [3]]);
     *
     *     var three = [3];
     *     // for object-types, contents are not compared
     *     expect(three).to.not.be.oneOf([1, 2, [3]]);
     *     // comparing references works
     *     expect(three).to.be.oneOf([1, 2, three]);
     *
     * @name oneOf
     * @param {Array<*>} list
     * @param {String} message _optional_
     * @api public
     */
  
    function oneOf (list, msg) {
      if (msg) flag(this, 'message', msg);
      var expected = flag(this, 'object');
      new Assertion(list).to.be.an('array');
  
      this.assert(
          list.indexOf(expected) > -1
        , 'expected #{this} to be one of #{exp}'
        , 'expected #{this} to not be one of #{exp}'
        , list
        , expected
      );
    }
  
    Assertion.addMethod('oneOf', oneOf);
  
  
    /**
     * ### .change(function)
     *
     * Asserts that a function changes an object property
     *
     *     var obj = { val: 10 };
     *     var fn = function() { obj.val += 3 };
     *     var noChangeFn = function() { return 'foo' + 'bar'; }
     *     expect(fn).to.change(obj, 'val');
     *     expect(noChangFn).to.not.change(obj, 'val')
     *
     * @name change
     * @alias changes
     * @alias Change
     * @param {String} object
     * @param {String} property name
     * @param {String} message _optional_
     * @api public
     */
  
    function assertChanges (object, prop, msg) {
      if (msg) flag(this, 'message', msg);
      var fn = flag(this, 'object');
      new Assertion(object, msg).to.have.property(prop);
      new Assertion(fn).is.a('function');
  
      var initial = object[prop];
      fn();
  
      this.assert(
        initial !== object[prop]
        , 'expected .' + prop + ' to change'
        , 'expected .' + prop + ' to not change'
      );
    }
  
    Assertion.addChainableMethod('change', assertChanges);
    Assertion.addChainableMethod('changes', assertChanges);
  
    /**
     * ### .increase(function)
     *
     * Asserts that a function increases an object property
     *
     *     var obj = { val: 10 };
     *     var fn = function() { obj.val = 15 };
     *     expect(fn).to.increase(obj, 'val');
     *
     * @name increase
     * @alias increases
     * @alias Increase
     * @param {String} object
     * @param {String} property name
     * @param {String} message _optional_
     * @api public
     */
  
    function assertIncreases (object, prop, msg) {
      if (msg) flag(this, 'message', msg);
      var fn = flag(this, 'object');
      new Assertion(object, msg).to.have.property(prop);
      new Assertion(fn).is.a('function');
  
      var initial = object[prop];
      fn();
  
      this.assert(
        object[prop] - initial > 0
        , 'expected .' + prop + ' to increase'
        , 'expected .' + prop + ' to not increase'
      );
    }
  
    Assertion.addChainableMethod('increase', assertIncreases);
    Assertion.addChainableMethod('increases', assertIncreases);
  
    /**
     * ### .decrease(function)
     *
     * Asserts that a function decreases an object property
     *
     *     var obj = { val: 10 };
     *     var fn = function() { obj.val = 5 };
     *     expect(fn).to.decrease(obj, 'val');
     *
     * @name decrease
     * @alias decreases
     * @alias Decrease
     * @param {String} object
     * @param {String} property name
     * @param {String} message _optional_
     * @api public
     */
  
    function assertDecreases (object, prop, msg) {
      if (msg) flag(this, 'message', msg);
      var fn = flag(this, 'object');
      new Assertion(object, msg).to.have.property(prop);
      new Assertion(fn).is.a('function');
  
      var initial = object[prop];
      fn();
  
      this.assert(
        object[prop] - initial < 0
        , 'expected .' + prop + ' to decrease'
        , 'expected .' + prop + ' to not decrease'
      );
    }
  
    Assertion.addChainableMethod('decrease', assertDecreases);
    Assertion.addChainableMethod('decreases', assertDecreases);
  
    /**
     * ### .extensible
     *
     * Asserts that the target is extensible (can have new properties added to
     * it).
     *
     *     var nonExtensibleObject = Object.preventExtensions({});
     *     var sealedObject = Object.seal({});
     *     var frozenObject = Object.freeze({});
     *
     *     expect({}).to.be.extensible;
     *     expect(nonExtensibleObject).to.not.be.extensible;
     *     expect(sealedObject).to.not.be.extensible;
     *     expect(frozenObject).to.not.be.extensible;
     *
     * @name extensible
     * @api public
     */
  
    Assertion.addProperty('extensible', function() {
      var obj = flag(this, 'object');
  
      // In ES5, if the argument to this method is not an object (a primitive), then it will cause a TypeError.
      // In ES6, a non-object argument will be treated as if it was a non-extensible ordinary object, simply return false.
      // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible
      // The following provides ES6 behavior when a TypeError is thrown under ES5.
  
      var isExtensible;
  
      try {
        isExtensible = Object.isExtensible(obj);
      } catch (err) {
        if (err instanceof TypeError) isExtensible = false;
        else throw err;
      }
  
      this.assert(
        isExtensible
        , 'expected #{this} to be extensible'
        , 'expected #{this} to not be extensible'
      );
    });
  
    /**
     * ### .sealed
     *
     * Asserts that the target is sealed (cannot have new properties added to it
     * and its existing properties cannot be removed).
     *
     *     var sealedObject = Object.seal({});
     *     var frozenObject = Object.freeze({});
     *
     *     expect(sealedObject).to.be.sealed;
     *     expect(frozenObject).to.be.sealed;
     *     expect({}).to.not.be.sealed;
     *
     * @name sealed
     * @api public
     */
  
    Assertion.addProperty('sealed', function() {
      var obj = flag(this, 'object');
  
      // In ES5, if the argument to this method is not an object (a primitive), then it will cause a TypeError.
      // In ES6, a non-object argument will be treated as if it was a sealed ordinary object, simply return true.
      // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isSealed
      // The following provides ES6 behavior when a TypeError is thrown under ES5.
  
      var isSealed;
  
      try {
        isSealed = Object.isSealed(obj);
      } catch (err) {
        if (err instanceof TypeError) isSealed = true;
        else throw err;
      }
  
      this.assert(
        isSealed
        , 'expected #{this} to be sealed'
        , 'expected #{this} to not be sealed'
      );
    });
  
    /**
     * ### .frozen
     *
     * Asserts that the target is frozen (cannot have new properties added to it
     * and its existing properties cannot be modified).
     *
     *     var frozenObject = Object.freeze({});
     *
     *     expect(frozenObject).to.be.frozen;
     *     expect({}).to.not.be.frozen;
     *
     * @name frozen
     * @api public
     */
  
    Assertion.addProperty('frozen', function() {
      var obj = flag(this, 'object');
  
      // In ES5, if the argument to this method is not an object (a primitive), then it will cause a TypeError.
      // In ES6, a non-object argument will be treated as if it was a frozen ordinary object, simply return true.
      // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isFrozen
      // The following provides ES6 behavior when a TypeError is thrown under ES5.
  
      var isFrozen;
  
      try {
        isFrozen = Object.isFrozen(obj);
      } catch (err) {
        if (err instanceof TypeError) isFrozen = true;
        else throw err;
      }
  
      this.assert(
        isFrozen
        , 'expected #{this} to be frozen'
        , 'expected #{this} to not be frozen'
      );
    });
  };
  
  },{}],61:[function(require,module,exports){
  /*!
   * chai
   * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  
  module.exports = function (chai, util) {
  
    /*!
     * Chai dependencies.
     */
  
    var Assertion = chai.Assertion
      , flag = util.flag;
  
    /*!
     * Module export.
     */
  
    /**
     * ### assert(expression, message)
     *
     * Write your own test expressions.
     *
     *     assert('foo' !== 'bar', 'foo is not bar');
     *     assert(Array.isArray([]), 'empty arrays are arrays');
     *
     * @param {Mixed} expression to test for truthiness
     * @param {String} message to display on error
     * @name assert
     * @api public
     */
  
    var assert = chai.assert = function (express, errmsg) {
      var test = new Assertion(null, null, chai.assert);
      test.assert(
          express
        , errmsg
        , '[ negation message unavailable ]'
      );
    };
  
    /**
     * ### .fail(actual, expected, [message], [operator])
     *
     * Throw a failure. Node.js `assert` module-compatible.
     *
     * @name fail
     * @param {Mixed} actual
     * @param {Mixed} expected
     * @param {String} message
     * @param {String} operator
     * @api public
     */
  
    assert.fail = function (actual, expected, message, operator) {
      message = message || 'assert.fail()';
      throw new chai.AssertionError(message, {
          actual: actual
        , expected: expected
        , operator: operator
      }, assert.fail);
    };
  
    /**
     * ### .isOk(object, [message])
     *
     * Asserts that `object` is truthy.
     *
     *     assert.isOk('everything', 'everything is ok');
     *     assert.isOk(false, 'this will fail');
     *
     * @name isOk
     * @alias ok
     * @param {Mixed} object to test
     * @param {String} message
     * @api public
     */
  
    assert.isOk = function (val, msg) {
      new Assertion(val, msg).is.ok;
    };
  
    /**
     * ### .isNotOk(object, [message])
     *
     * Asserts that `object` is falsy.
     *
     *     assert.isNotOk('everything', 'this will fail');
     *     assert.isNotOk(false, 'this will pass');
     *
     * @name isNotOk
     * @alias notOk
     * @param {Mixed} object to test
     * @param {String} message
     * @api public
     */
  
    assert.isNotOk = function (val, msg) {
      new Assertion(val, msg).is.not.ok;
    };
  
    /**
     * ### .equal(actual, expected, [message])
     *
     * Asserts non-strict equality (`==`) of `actual` and `expected`.
     *
     *     assert.equal(3, '3', '== coerces values to strings');
     *
     * @name equal
     * @param {Mixed} actual
     * @param {Mixed} expected
     * @param {String} message
     * @api public
     */
  
    assert.equal = function (act, exp, msg) {
      var test = new Assertion(act, msg, assert.equal);
  
      test.assert(
          exp == flag(test, 'object')
        , 'expected #{this} to equal #{exp}'
        , 'expected #{this} to not equal #{act}'
        , exp
        , act
      );
    };
  
    /**
     * ### .notEqual(actual, expected, [message])
     *
     * Asserts non-strict inequality (`!=`) of `actual` and `expected`.
     *
     *     assert.notEqual(3, 4, 'these numbers are not equal');
     *
     * @name notEqual
     * @param {Mixed} actual
     * @param {Mixed} expected
     * @param {String} message
     * @api public
     */
  
    assert.notEqual = function (act, exp, msg) {
      var test = new Assertion(act, msg, assert.notEqual);
  
      test.assert(
          exp != flag(test, 'object')
        , 'expected #{this} to not equal #{exp}'
        , 'expected #{this} to equal #{act}'
        , exp
        , act
      );
    };
  
    /**
     * ### .strictEqual(actual, expected, [message])
     *
     * Asserts strict equality (`===`) of `actual` and `expected`.
     *
     *     assert.strictEqual(true, true, 'these booleans are strictly equal');
     *
     * @name strictEqual
     * @param {Mixed} actual
     * @param {Mixed} expected
     * @param {String} message
     * @api public
     */
  
    assert.strictEqual = function (act, exp, msg) {
      new Assertion(act, msg).to.equal(exp);
    };
  
    /**
     * ### .notStrictEqual(actual, expected, [message])
     *
     * Asserts strict inequality (`!==`) of `actual` and `expected`.
     *
     *     assert.notStrictEqual(3, '3', 'no coercion for strict equality');
     *
     * @name notStrictEqual
     * @param {Mixed} actual
     * @param {Mixed} expected
     * @param {String} message
     * @api public
     */
  
    assert.notStrictEqual = function (act, exp, msg) {
      new Assertion(act, msg).to.not.equal(exp);
    };
  
    /**
     * ### .deepEqual(actual, expected, [message])
     *
     * Asserts that `actual` is deeply equal to `expected`.
     *
     *     assert.deepEqual({ tea: 'green' }, { tea: 'green' });
     *
     * @name deepEqual
     * @param {Mixed} actual
     * @param {Mixed} expected
     * @param {String} message
     * @api public
     */
  
    assert.deepEqual = function (act, exp, msg) {
      new Assertion(act, msg).to.eql(exp);
    };
  
    /**
     * ### .notDeepEqual(actual, expected, [message])
     *
     * Assert that `actual` is not deeply equal to `expected`.
     *
     *     assert.notDeepEqual({ tea: 'green' }, { tea: 'jasmine' });
     *
     * @name notDeepEqual
     * @param {Mixed} actual
     * @param {Mixed} expected
     * @param {String} message
     * @api public
     */
  
    assert.notDeepEqual = function (act, exp, msg) {
      new Assertion(act, msg).to.not.eql(exp);
    };
  
     /**
     * ### .isAbove(valueToCheck, valueToBeAbove, [message])
     *
     * Asserts `valueToCheck` is strictly greater than (>) `valueToBeAbove`
     *
     *     assert.isAbove(5, 2, '5 is strictly greater than 2');
     *
     * @name isAbove
     * @param {Mixed} valueToCheck
     * @param {Mixed} valueToBeAbove
     * @param {String} message
     * @api public
     */
  
    assert.isAbove = function (val, abv, msg) {
      new Assertion(val, msg).to.be.above(abv);
    };
  
     /**
     * ### .isAtLeast(valueToCheck, valueToBeAtLeast, [message])
     *
     * Asserts `valueToCheck` is greater than or equal to (>=) `valueToBeAtLeast`
     *
     *     assert.isAtLeast(5, 2, '5 is greater or equal to 2');
     *     assert.isAtLeast(3, 3, '3 is greater or equal to 3');
     *
     * @name isAtLeast
     * @param {Mixed} valueToCheck
     * @param {Mixed} valueToBeAtLeast
     * @param {String} message
     * @api public
     */
  
    assert.isAtLeast = function (val, atlst, msg) {
      new Assertion(val, msg).to.be.least(atlst);
    };
  
     /**
     * ### .isBelow(valueToCheck, valueToBeBelow, [message])
     *
     * Asserts `valueToCheck` is strictly less than (<) `valueToBeBelow`
     *
     *     assert.isBelow(3, 6, '3 is strictly less than 6');
     *
     * @name isBelow
     * @param {Mixed} valueToCheck
     * @param {Mixed} valueToBeBelow
     * @param {String} message
     * @api public
     */
  
    assert.isBelow = function (val, blw, msg) {
      new Assertion(val, msg).to.be.below(blw);
    };
  
     /**
     * ### .isAtMost(valueToCheck, valueToBeAtMost, [message])
     *
     * Asserts `valueToCheck` is less than or equal to (<=) `valueToBeAtMost`
     *
     *     assert.isAtMost(3, 6, '3 is less than or equal to 6');
     *     assert.isAtMost(4, 4, '4 is less than or equal to 4');
     *
     * @name isAtMost
     * @param {Mixed} valueToCheck
     * @param {Mixed} valueToBeAtMost
     * @param {String} message
     * @api public
     */
  
    assert.isAtMost = function (val, atmst, msg) {
      new Assertion(val, msg).to.be.most(atmst);
    };
  
    /**
     * ### .isTrue(value, [message])
     *
     * Asserts that `value` is true.
     *
     *     var teaServed = true;
     *     assert.isTrue(teaServed, 'the tea has been served');
     *
     * @name isTrue
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isTrue = function (val, msg) {
      new Assertion(val, msg).is['true'];
    };
  
    /**
     * ### .isNotTrue(value, [message])
     *
     * Asserts that `value` is not true.
     *
     *     var tea = 'tasty chai';
     *     assert.isNotTrue(tea, 'great, time for tea!');
     *
     * @name isNotTrue
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isNotTrue = function (val, msg) {
      new Assertion(val, msg).to.not.equal(true);
    };
  
    /**
     * ### .isFalse(value, [message])
     *
     * Asserts that `value` is false.
     *
     *     var teaServed = false;
     *     assert.isFalse(teaServed, 'no tea yet? hmm...');
     *
     * @name isFalse
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isFalse = function (val, msg) {
      new Assertion(val, msg).is['false'];
    };
  
    /**
     * ### .isNotFalse(value, [message])
     *
     * Asserts that `value` is not false.
     *
     *     var tea = 'tasty chai';
     *     assert.isNotFalse(tea, 'great, time for tea!');
     *
     * @name isNotFalse
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isNotFalse = function (val, msg) {
      new Assertion(val, msg).to.not.equal(false);
    };
  
    /**
     * ### .isNull(value, [message])
     *
     * Asserts that `value` is null.
     *
     *     assert.isNull(err, 'there was no error');
     *
     * @name isNull
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isNull = function (val, msg) {
      new Assertion(val, msg).to.equal(null);
    };
  
    /**
     * ### .isNotNull(value, [message])
     *
     * Asserts that `value` is not null.
     *
     *     var tea = 'tasty chai';
     *     assert.isNotNull(tea, 'great, time for tea!');
     *
     * @name isNotNull
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isNotNull = function (val, msg) {
      new Assertion(val, msg).to.not.equal(null);
    };
  
    /**
     * ### .isNaN
     * Asserts that value is NaN
     *
     *    assert.isNaN('foo', 'foo is NaN');
     *
     * @name isNaN
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isNaN = function (val, msg) {
      new Assertion(val, msg).to.be.NaN;
    };
  
    /**
     * ### .isNotNaN
     * Asserts that value is not NaN
     *
     *    assert.isNotNaN(4, '4 is not NaN');
     *
     * @name isNotNaN
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
    assert.isNotNaN = function (val, msg) {
      new Assertion(val, msg).not.to.be.NaN;
    };
  
    /**
     * ### .isUndefined(value, [message])
     *
     * Asserts that `value` is `undefined`.
     *
     *     var tea;
     *     assert.isUndefined(tea, 'no tea defined');
     *
     * @name isUndefined
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isUndefined = function (val, msg) {
      new Assertion(val, msg).to.equal(undefined);
    };
  
    /**
     * ### .isDefined(value, [message])
     *
     * Asserts that `value` is not `undefined`.
     *
     *     var tea = 'cup of chai';
     *     assert.isDefined(tea, 'tea has been defined');
     *
     * @name isDefined
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isDefined = function (val, msg) {
      new Assertion(val, msg).to.not.equal(undefined);
    };
  
    /**
     * ### .isFunction(value, [message])
     *
     * Asserts that `value` is a function.
     *
     *     function serveTea() { return 'cup of tea'; };
     *     assert.isFunction(serveTea, 'great, we can have tea now');
     *
     * @name isFunction
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isFunction = function (val, msg) {
      new Assertion(val, msg).to.be.a('function');
    };
  
    /**
     * ### .isNotFunction(value, [message])
     *
     * Asserts that `value` is _not_ a function.
     *
     *     var serveTea = [ 'heat', 'pour', 'sip' ];
     *     assert.isNotFunction(serveTea, 'great, we have listed the steps');
     *
     * @name isNotFunction
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isNotFunction = function (val, msg) {
      new Assertion(val, msg).to.not.be.a('function');
    };
  
    /**
     * ### .isObject(value, [message])
     *
     * Asserts that `value` is an object (as revealed by
     * `Object.prototype.toString`).
     *
     *     var selection = { name: 'Chai', serve: 'with spices' };
     *     assert.isObject(selection, 'tea selection is an object');
     *
     * @name isObject
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isObject = function (val, msg) {
      new Assertion(val, msg).to.be.a('object');
    };
  
    /**
     * ### .isNotObject(value, [message])
     *
     * Asserts that `value` is _not_ an object.
     *
     *     var selection = 'chai'
     *     assert.isNotObject(selection, 'tea selection is not an object');
     *     assert.isNotObject(null, 'null is not an object');
     *
     * @name isNotObject
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isNotObject = function (val, msg) {
      new Assertion(val, msg).to.not.be.a('object');
    };
  
    /**
     * ### .isArray(value, [message])
     *
     * Asserts that `value` is an array.
     *
     *     var menu = [ 'green', 'chai', 'oolong' ];
     *     assert.isArray(menu, 'what kind of tea do we want?');
     *
     * @name isArray
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isArray = function (val, msg) {
      new Assertion(val, msg).to.be.an('array');
    };
  
    /**
     * ### .isNotArray(value, [message])
     *
     * Asserts that `value` is _not_ an array.
     *
     *     var menu = 'green|chai|oolong';
     *     assert.isNotArray(menu, 'what kind of tea do we want?');
     *
     * @name isNotArray
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isNotArray = function (val, msg) {
      new Assertion(val, msg).to.not.be.an('array');
    };
  
    /**
     * ### .isString(value, [message])
     *
     * Asserts that `value` is a string.
     *
     *     var teaOrder = 'chai';
     *     assert.isString(teaOrder, 'order placed');
     *
     * @name isString
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isString = function (val, msg) {
      new Assertion(val, msg).to.be.a('string');
    };
  
    /**
     * ### .isNotString(value, [message])
     *
     * Asserts that `value` is _not_ a string.
     *
     *     var teaOrder = 4;
     *     assert.isNotString(teaOrder, 'order placed');
     *
     * @name isNotString
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isNotString = function (val, msg) {
      new Assertion(val, msg).to.not.be.a('string');
    };
  
    /**
     * ### .isNumber(value, [message])
     *
     * Asserts that `value` is a number.
     *
     *     var cups = 2;
     *     assert.isNumber(cups, 'how many cups');
     *
     * @name isNumber
     * @param {Number} value
     * @param {String} message
     * @api public
     */
  
    assert.isNumber = function (val, msg) {
      new Assertion(val, msg).to.be.a('number');
    };
  
    /**
     * ### .isNotNumber(value, [message])
     *
     * Asserts that `value` is _not_ a number.
     *
     *     var cups = '2 cups please';
     *     assert.isNotNumber(cups, 'how many cups');
     *
     * @name isNotNumber
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isNotNumber = function (val, msg) {
      new Assertion(val, msg).to.not.be.a('number');
    };
  
    /**
     * ### .isBoolean(value, [message])
     *
     * Asserts that `value` is a boolean.
     *
     *     var teaReady = true
     *       , teaServed = false;
     *
     *     assert.isBoolean(teaReady, 'is the tea ready');
     *     assert.isBoolean(teaServed, 'has tea been served');
     *
     * @name isBoolean
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isBoolean = function (val, msg) {
      new Assertion(val, msg).to.be.a('boolean');
    };
  
    /**
     * ### .isNotBoolean(value, [message])
     *
     * Asserts that `value` is _not_ a boolean.
     *
     *     var teaReady = 'yep'
     *       , teaServed = 'nope';
     *
     *     assert.isNotBoolean(teaReady, 'is the tea ready');
     *     assert.isNotBoolean(teaServed, 'has tea been served');
     *
     * @name isNotBoolean
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isNotBoolean = function (val, msg) {
      new Assertion(val, msg).to.not.be.a('boolean');
    };
  
    /**
     * ### .typeOf(value, name, [message])
     *
     * Asserts that `value`'s type is `name`, as determined by
     * `Object.prototype.toString`.
     *
     *     assert.typeOf({ tea: 'chai' }, 'object', 'we have an object');
     *     assert.typeOf(['chai', 'jasmine'], 'array', 'we have an array');
     *     assert.typeOf('tea', 'string', 'we have a string');
     *     assert.typeOf(/tea/, 'regexp', 'we have a regular expression');
     *     assert.typeOf(null, 'null', 'we have a null');
     *     assert.typeOf(undefined, 'undefined', 'we have an undefined');
     *
     * @name typeOf
     * @param {Mixed} value
     * @param {String} name
     * @param {String} message
     * @api public
     */
  
    assert.typeOf = function (val, type, msg) {
      new Assertion(val, msg).to.be.a(type);
    };
  
    /**
     * ### .notTypeOf(value, name, [message])
     *
     * Asserts that `value`'s type is _not_ `name`, as determined by
     * `Object.prototype.toString`.
     *
     *     assert.notTypeOf('tea', 'number', 'strings are not numbers');
     *
     * @name notTypeOf
     * @param {Mixed} value
     * @param {String} typeof name
     * @param {String} message
     * @api public
     */
  
    assert.notTypeOf = function (val, type, msg) {
      new Assertion(val, msg).to.not.be.a(type);
    };
  
    /**
     * ### .instanceOf(object, constructor, [message])
     *
     * Asserts that `value` is an instance of `constructor`.
     *
     *     var Tea = function (name) { this.name = name; }
     *       , chai = new Tea('chai');
     *
     *     assert.instanceOf(chai, Tea, 'chai is an instance of tea');
     *
     * @name instanceOf
     * @param {Object} object
     * @param {Constructor} constructor
     * @param {String} message
     * @api public
     */
  
    assert.instanceOf = function (val, type, msg) {
      new Assertion(val, msg).to.be.instanceOf(type);
    };
  
    /**
     * ### .notInstanceOf(object, constructor, [message])
     *
     * Asserts `value` is not an instance of `constructor`.
     *
     *     var Tea = function (name) { this.name = name; }
     *       , chai = new String('chai');
     *
     *     assert.notInstanceOf(chai, Tea, 'chai is not an instance of tea');
     *
     * @name notInstanceOf
     * @param {Object} object
     * @param {Constructor} constructor
     * @param {String} message
     * @api public
     */
  
    assert.notInstanceOf = function (val, type, msg) {
      new Assertion(val, msg).to.not.be.instanceOf(type);
    };
  
    /**
     * ### .include(haystack, needle, [message])
     *
     * Asserts that `haystack` includes `needle`. Works
     * for strings and arrays.
     *
     *     assert.include('foobar', 'bar', 'foobar contains string "bar"');
     *     assert.include([ 1, 2, 3 ], 3, 'array contains value');
     *
     * @name include
     * @param {Array|String} haystack
     * @param {Mixed} needle
     * @param {String} message
     * @api public
     */
  
    assert.include = function (exp, inc, msg) {
      new Assertion(exp, msg, assert.include).include(inc);
    };
  
    /**
     * ### .notInclude(haystack, needle, [message])
     *
     * Asserts that `haystack` does not include `needle`. Works
     * for strings and arrays.
     *
     *     assert.notInclude('foobar', 'baz', 'string not include substring');
     *     assert.notInclude([ 1, 2, 3 ], 4, 'array not include contain value');
     *
     * @name notInclude
     * @param {Array|String} haystack
     * @param {Mixed} needle
     * @param {String} message
     * @api public
     */
  
    assert.notInclude = function (exp, inc, msg) {
      new Assertion(exp, msg, assert.notInclude).not.include(inc);
    };
  
    /**
     * ### .match(value, regexp, [message])
     *
     * Asserts that `value` matches the regular expression `regexp`.
     *
     *     assert.match('foobar', /^foo/, 'regexp matches');
     *
     * @name match
     * @param {Mixed} value
     * @param {RegExp} regexp
     * @param {String} message
     * @api public
     */
  
    assert.match = function (exp, re, msg) {
      new Assertion(exp, msg).to.match(re);
    };
  
    /**
     * ### .notMatch(value, regexp, [message])
     *
     * Asserts that `value` does not match the regular expression `regexp`.
     *
     *     assert.notMatch('foobar', /^foo/, 'regexp does not match');
     *
     * @name notMatch
     * @param {Mixed} value
     * @param {RegExp} regexp
     * @param {String} message
     * @api public
     */
  
    assert.notMatch = function (exp, re, msg) {
      new Assertion(exp, msg).to.not.match(re);
    };
  
    /**
     * ### .property(object, property, [message])
     *
     * Asserts that `object` has a property named by `property`.
     *
     *     assert.property({ tea: { green: 'matcha' }}, 'tea');
     *
     * @name property
     * @param {Object} object
     * @param {String} property
     * @param {String} message
     * @api public
     */
  
    assert.property = function (obj, prop, msg) {
      new Assertion(obj, msg).to.have.property(prop);
    };
  
    /**
     * ### .notProperty(object, property, [message])
     *
     * Asserts that `object` does _not_ have a property named by `property`.
     *
     *     assert.notProperty({ tea: { green: 'matcha' }}, 'coffee');
     *
     * @name notProperty
     * @param {Object} object
     * @param {String} property
     * @param {String} message
     * @api public
     */
  
    assert.notProperty = function (obj, prop, msg) {
      new Assertion(obj, msg).to.not.have.property(prop);
    };
  
    /**
     * ### .deepProperty(object, property, [message])
     *
     * Asserts that `object` has a property named by `property`, which can be a
     * string using dot- and bracket-notation for deep reference.
     *
     *     assert.deepProperty({ tea: { green: 'matcha' }}, 'tea.green');
     *
     * @name deepProperty
     * @param {Object} object
     * @param {String} property
     * @param {String} message
     * @api public
     */
  
    assert.deepProperty = function (obj, prop, msg) {
      new Assertion(obj, msg).to.have.deep.property(prop);
    };
  
    /**
     * ### .notDeepProperty(object, property, [message])
     *
     * Asserts that `object` does _not_ have a property named by `property`, which
     * can be a string using dot- and bracket-notation for deep reference.
     *
     *     assert.notDeepProperty({ tea: { green: 'matcha' }}, 'tea.oolong');
     *
     * @name notDeepProperty
     * @param {Object} object
     * @param {String} property
     * @param {String} message
     * @api public
     */
  
    assert.notDeepProperty = function (obj, prop, msg) {
      new Assertion(obj, msg).to.not.have.deep.property(prop);
    };
  
    /**
     * ### .propertyVal(object, property, value, [message])
     *
     * Asserts that `object` has a property named by `property` with value given
     * by `value`.
     *
     *     assert.propertyVal({ tea: 'is good' }, 'tea', 'is good');
     *
     * @name propertyVal
     * @param {Object} object
     * @param {String} property
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.propertyVal = function (obj, prop, val, msg) {
      new Assertion(obj, msg).to.have.property(prop, val);
    };
  
    /**
     * ### .propertyNotVal(object, property, value, [message])
     *
     * Asserts that `object` has a property named by `property`, but with a value
     * different from that given by `value`.
     *
     *     assert.propertyNotVal({ tea: 'is good' }, 'tea', 'is bad');
     *
     * @name propertyNotVal
     * @param {Object} object
     * @param {String} property
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.propertyNotVal = function (obj, prop, val, msg) {
      new Assertion(obj, msg).to.not.have.property(prop, val);
    };
  
    /**
     * ### .deepPropertyVal(object, property, value, [message])
     *
     * Asserts that `object` has a property named by `property` with value given
     * by `value`. `property` can use dot- and bracket-notation for deep
     * reference.
     *
     *     assert.deepPropertyVal({ tea: { green: 'matcha' }}, 'tea.green', 'matcha');
     *
     * @name deepPropertyVal
     * @param {Object} object
     * @param {String} property
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.deepPropertyVal = function (obj, prop, val, msg) {
      new Assertion(obj, msg).to.have.deep.property(prop, val);
    };
  
    /**
     * ### .deepPropertyNotVal(object, property, value, [message])
     *
     * Asserts that `object` has a property named by `property`, but with a value
     * different from that given by `value`. `property` can use dot- and
     * bracket-notation for deep reference.
     *
     *     assert.deepPropertyNotVal({ tea: { green: 'matcha' }}, 'tea.green', 'konacha');
     *
     * @name deepPropertyNotVal
     * @param {Object} object
     * @param {String} property
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.deepPropertyNotVal = function (obj, prop, val, msg) {
      new Assertion(obj, msg).to.not.have.deep.property(prop, val);
    };
  
    /**
     * ### .lengthOf(object, length, [message])
     *
     * Asserts that `object` has a `length` property with the expected value.
     *
     *     assert.lengthOf([1,2,3], 3, 'array has length of 3');
     *     assert.lengthOf('foobar', 6, 'string has length of 6');
     *
     * @name lengthOf
     * @param {Mixed} object
     * @param {Number} length
     * @param {String} message
     * @api public
     */
  
    assert.lengthOf = function (exp, len, msg) {
      new Assertion(exp, msg).to.have.length(len);
    };
  
    /**
     * ### .throws(function, [constructor/string/regexp], [string/regexp], [message])
     *
     * Asserts that `function` will throw an error that is an instance of
     * `constructor`, or alternately that it will throw an error with message
     * matching `regexp`.
     *
     *     assert.throws(fn, 'function throws a reference error');
     *     assert.throws(fn, /function throws a reference error/);
     *     assert.throws(fn, ReferenceError);
     *     assert.throws(fn, ReferenceError, 'function throws a reference error');
     *     assert.throws(fn, ReferenceError, /function throws a reference error/);
     *
     * @name throws
     * @alias throw
     * @alias Throw
     * @param {Function} function
     * @param {ErrorConstructor} constructor
     * @param {RegExp} regexp
     * @param {String} message
     * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
     * @api public
     */
  
    assert.throws = function (fn, errt, errs, msg) {
      if ('string' === typeof errt || errt instanceof RegExp) {
        errs = errt;
        errt = null;
      }
  
      var assertErr = new Assertion(fn, msg).to.throw(errt, errs);
      return flag(assertErr, 'object');
    };
  
    /**
     * ### .doesNotThrow(function, [constructor/regexp], [message])
     *
     * Asserts that `function` will _not_ throw an error that is an instance of
     * `constructor`, or alternately that it will not throw an error with message
     * matching `regexp`.
     *
     *     assert.doesNotThrow(fn, Error, 'function does not throw');
     *
     * @name doesNotThrow
     * @param {Function} function
     * @param {ErrorConstructor} constructor
     * @param {RegExp} regexp
     * @param {String} message
     * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
     * @api public
     */
  
    assert.doesNotThrow = function (fn, type, msg) {
      if ('string' === typeof type) {
        msg = type;
        type = null;
      }
  
      new Assertion(fn, msg).to.not.Throw(type);
    };
  
    /**
     * ### .operator(val1, operator, val2, [message])
     *
     * Compares two values using `operator`.
     *
     *     assert.operator(1, '<', 2, 'everything is ok');
     *     assert.operator(1, '>', 2, 'this will fail');
     *
     * @name operator
     * @param {Mixed} val1
     * @param {String} operator
     * @param {Mixed} val2
     * @param {String} message
     * @api public
     */
  
    assert.operator = function (val, operator, val2, msg) {
      var ok;
      switch(operator) {
        case '==':
          ok = val == val2;
          break;
        case '===':
          ok = val === val2;
          break;
        case '>':
          ok = val > val2;
          break;
        case '>=':
          ok = val >= val2;
          break;
        case '<':
          ok = val < val2;
          break;
        case '<=':
          ok = val <= val2;
          break;
        case '!=':
          ok = val != val2;
          break;
        case '!==':
          ok = val !== val2;
          break;
        default:
          throw new Error('Invalid operator "' + operator + '"');
      }
      var test = new Assertion(ok, msg);
      test.assert(
          true === flag(test, 'object')
        , 'expected ' + util.inspect(val) + ' to be ' + operator + ' ' + util.inspect(val2)
        , 'expected ' + util.inspect(val) + ' to not be ' + operator + ' ' + util.inspect(val2) );
    };
  
    /**
     * ### .closeTo(actual, expected, delta, [message])
     *
     * Asserts that the target is equal `expected`, to within a +/- `delta` range.
     *
     *     assert.closeTo(1.5, 1, 0.5, 'numbers are close');
     *
     * @name closeTo
     * @param {Number} actual
     * @param {Number} expected
     * @param {Number} delta
     * @param {String} message
     * @api public
     */
  
    assert.closeTo = function (act, exp, delta, msg) {
      new Assertion(act, msg).to.be.closeTo(exp, delta);
    };
  
    /**
     * ### .approximately(actual, expected, delta, [message])
     *
     * Asserts that the target is equal `expected`, to within a +/- `delta` range.
     *
     *     assert.approximately(1.5, 1, 0.5, 'numbers are close');
     *
     * @name approximately
     * @param {Number} actual
     * @param {Number} expected
     * @param {Number} delta
     * @param {String} message
     * @api public
     */
  
    assert.approximately = function (act, exp, delta, msg) {
      new Assertion(act, msg).to.be.approximately(exp, delta);
    };
  
    /**
     * ### .sameMembers(set1, set2, [message])
     *
     * Asserts that `set1` and `set2` have the same members.
     * Order is not taken into account.
     *
     *     assert.sameMembers([ 1, 2, 3 ], [ 2, 1, 3 ], 'same members');
     *
     * @name sameMembers
     * @param {Array} set1
     * @param {Array} set2
     * @param {String} message
     * @api public
     */
  
    assert.sameMembers = function (set1, set2, msg) {
      new Assertion(set1, msg).to.have.same.members(set2);
    }
  
    /**
     * ### .sameDeepMembers(set1, set2, [message])
     *
     * Asserts that `set1` and `set2` have the same members - using a deep equality checking.
     * Order is not taken into account.
     *
     *     assert.sameDeepMembers([ {b: 3}, {a: 2}, {c: 5} ], [ {c: 5}, {b: 3}, {a: 2} ], 'same deep members');
     *
     * @name sameDeepMembers
     * @param {Array} set1
     * @param {Array} set2
     * @param {String} message
     * @api public
     */
  
    assert.sameDeepMembers = function (set1, set2, msg) {
      new Assertion(set1, msg).to.have.same.deep.members(set2);
    }
  
    /**
     * ### .includeMembers(superset, subset, [message])
     *
     * Asserts that `subset` is included in `superset`.
     * Order is not taken into account.
     *
     *     assert.includeMembers([ 1, 2, 3 ], [ 2, 1 ], 'include members');
     *
     * @name includeMembers
     * @param {Array} superset
     * @param {Array} subset
     * @param {String} message
     * @api public
     */
  
    assert.includeMembers = function (superset, subset, msg) {
      new Assertion(superset, msg).to.include.members(subset);
    }
  
    /**
     * ### .oneOf(inList, list, [message])
     *
     * Asserts that non-object, non-array value `inList` appears in the flat array `list`.
     *
     *     assert.oneOf(1, [ 2, 1 ], 'Not found in list');
     *
     * @name oneOf
     * @param {*} inList
     * @param {Array<*>} list
     * @param {String} message
     * @api public
     */
  
    assert.oneOf = function (inList, list, msg) {
      new Assertion(inList, msg).to.be.oneOf(list);
    }
  
     /**
     * ### .changes(function, object, property)
     *
     * Asserts that a function changes the value of a property
     *
     *     var obj = { val: 10 };
     *     var fn = function() { obj.val = 22 };
     *     assert.changes(fn, obj, 'val');
     *
     * @name changes
     * @param {Function} modifier function
     * @param {Object} object
     * @param {String} property name
     * @param {String} message _optional_
     * @api public
     */
  
    assert.changes = function (fn, obj, prop) {
      new Assertion(fn).to.change(obj, prop);
    }
  
     /**
     * ### .doesNotChange(function, object, property)
     *
     * Asserts that a function does not changes the value of a property
     *
     *     var obj = { val: 10 };
     *     var fn = function() { console.log('foo'); };
     *     assert.doesNotChange(fn, obj, 'val');
     *
     * @name doesNotChange
     * @param {Function} modifier function
     * @param {Object} object
     * @param {String} property name
     * @param {String} message _optional_
     * @api public
     */
  
    assert.doesNotChange = function (fn, obj, prop) {
      new Assertion(fn).to.not.change(obj, prop);
    }
  
     /**
     * ### .increases(function, object, property)
     *
     * Asserts that a function increases an object property
     *
     *     var obj = { val: 10 };
     *     var fn = function() { obj.val = 13 };
     *     assert.increases(fn, obj, 'val');
     *
     * @name increases
     * @param {Function} modifier function
     * @param {Object} object
     * @param {String} property name
     * @param {String} message _optional_
     * @api public
     */
  
    assert.increases = function (fn, obj, prop) {
      new Assertion(fn).to.increase(obj, prop);
    }
  
     /**
     * ### .doesNotIncrease(function, object, property)
     *
     * Asserts that a function does not increase object property
     *
     *     var obj = { val: 10 };
     *     var fn = function() { obj.val = 8 };
     *     assert.doesNotIncrease(fn, obj, 'val');
     *
     * @name doesNotIncrease
     * @param {Function} modifier function
     * @param {Object} object
     * @param {String} property name
     * @param {String} message _optional_
     * @api public
     */
  
    assert.doesNotIncrease = function (fn, obj, prop) {
      new Assertion(fn).to.not.increase(obj, prop);
    }
  
     /**
     * ### .decreases(function, object, property)
     *
     * Asserts that a function decreases an object property
     *
     *     var obj = { val: 10 };
     *     var fn = function() { obj.val = 5 };
     *     assert.decreases(fn, obj, 'val');
     *
     * @name decreases
     * @param {Function} modifier function
     * @param {Object} object
     * @param {String} property name
     * @param {String} message _optional_
     * @api public
     */
  
    assert.decreases = function (fn, obj, prop) {
      new Assertion(fn).to.decrease(obj, prop);
    }
  
     /**
     * ### .doesNotDecrease(function, object, property)
     *
     * Asserts that a function does not decreases an object property
     *
     *     var obj = { val: 10 };
     *     var fn = function() { obj.val = 15 };
     *     assert.doesNotDecrease(fn, obj, 'val');
     *
     * @name doesNotDecrease
     * @param {Function} modifier function
     * @param {Object} object
     * @param {String} property name
     * @param {String} message _optional_
     * @api public
     */
  
    assert.doesNotDecrease = function (fn, obj, prop) {
      new Assertion(fn).to.not.decrease(obj, prop);
    }
  
    /*!
     * ### .ifError(object)
     *
     * Asserts if value is not a false value, and throws if it is a true value.
     * This is added to allow for chai to be a drop-in replacement for Node's
     * assert class.
     *
     *     var err = new Error('I am a custom error');
     *     assert.ifError(err); // Rethrows err!
     *
     * @name ifError
     * @param {Object} object
     * @api public
     */
  
    assert.ifError = function (val) {
      if (val) {
        throw(val);
      }
    };
  
    /**
     * ### .isExtensible(object)
     *
     * Asserts that `object` is extensible (can have new properties added to it).
     *
     *     assert.isExtensible({});
     *
     * @name isExtensible
     * @alias extensible
     * @param {Object} object
     * @param {String} message _optional_
     * @api public
     */
  
    assert.isExtensible = function (obj, msg) {
      new Assertion(obj, msg).to.be.extensible;
    };
  
    /**
     * ### .isNotExtensible(object)
     *
     * Asserts that `object` is _not_ extensible.
     *
     *     var nonExtensibleObject = Object.preventExtensions({});
     *     var sealedObject = Object.seal({});
     *     var frozenObject = Object.freese({});
     *
     *     assert.isNotExtensible(nonExtensibleObject);
     *     assert.isNotExtensible(sealedObject);
     *     assert.isNotExtensible(frozenObject);
     *
     * @name isNotExtensible
     * @alias notExtensible
     * @param {Object} object
     * @param {String} message _optional_
     * @api public
     */
  
    assert.isNotExtensible = function (obj, msg) {
      new Assertion(obj, msg).to.not.be.extensible;
    };
  
    /**
     * ### .isSealed(object)
     *
     * Asserts that `object` is sealed (cannot have new properties added to it
     * and its existing properties cannot be removed).
     *
     *     var sealedObject = Object.seal({});
     *     var frozenObject = Object.seal({});
     *
     *     assert.isSealed(sealedObject);
     *     assert.isSealed(frozenObject);
     *
     * @name isSealed
     * @alias sealed
     * @param {Object} object
     * @param {String} message _optional_
     * @api public
     */
  
    assert.isSealed = function (obj, msg) {
      new Assertion(obj, msg).to.be.sealed;
    };
  
    /**
     * ### .isNotSealed(object)
     *
     * Asserts that `object` is _not_ sealed.
     *
     *     assert.isNotSealed({});
     *
     * @name isNotSealed
     * @alias notSealed
     * @param {Object} object
     * @param {String} message _optional_
     * @api public
     */
  
    assert.isNotSealed = function (obj, msg) {
      new Assertion(obj, msg).to.not.be.sealed;
    };
  
    /**
     * ### .isFrozen(object)
     *
     * Asserts that `object` is frozen (cannot have new properties added to it
     * and its existing properties cannot be modified).
     *
     *     var frozenObject = Object.freeze({});
     *     assert.frozen(frozenObject);
     *
     * @name isFrozen
     * @alias frozen
     * @param {Object} object
     * @param {String} message _optional_
     * @api public
     */
  
    assert.isFrozen = function (obj, msg) {
      new Assertion(obj, msg).to.be.frozen;
    };
  
    /**
     * ### .isNotFrozen(object)
     *
     * Asserts that `object` is _not_ frozen.
     *
     *     assert.isNotFrozen({});
     *
     * @name isNotFrozen
     * @alias notFrozen
     * @param {Object} object
     * @param {String} message _optional_
     * @api public
     */
  
    assert.isNotFrozen = function (obj, msg) {
      new Assertion(obj, msg).to.not.be.frozen;
    };
  
    /*!
     * Aliases.
     */
  
    (function alias(name, as){
      assert[as] = assert[name];
      return alias;
    })
    ('isOk', 'ok')
    ('isNotOk', 'notOk')
    ('throws', 'throw')
    ('throws', 'Throw')
    ('isExtensible', 'extensible')
    ('isNotExtensible', 'notExtensible')
    ('isSealed', 'sealed')
    ('isNotSealed', 'notSealed')
    ('isFrozen', 'frozen')
    ('isNotFrozen', 'notFrozen');
  };
  
  },{}],62:[function(require,module,exports){
  /*!
   * chai
   * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  module.exports = function (chai, util) {
    chai.expect = function (val, message) {
      return new chai.Assertion(val, message);
    };
  
    /**
     * ### .fail(actual, expected, [message], [operator])
     *
     * Throw a failure.
     *
     * @name fail
     * @param {Mixed} actual
     * @param {Mixed} expected
     * @param {String} message
     * @param {String} operator
     * @api public
     */
  
    chai.expect.fail = function (actual, expected, message, operator) {
      message = message || 'expect.fail()';
      throw new chai.AssertionError(message, {
          actual: actual
        , expected: expected
        , operator: operator
      }, chai.expect.fail);
    };
  };
  
  },{}],63:[function(require,module,exports){
  /*!
   * chai
   * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  module.exports = function (chai, util) {
    var Assertion = chai.Assertion;
  
    function loadShould () {
      // explicitly define this method as function as to have it's name to include as `ssfi`
      function shouldGetter() {
        if (this instanceof String || this instanceof Number || this instanceof Boolean ) {
          return new Assertion(this.valueOf(), null, shouldGetter);
        }
        return new Assertion(this, null, shouldGetter);
      }
      function shouldSetter(value) {
        // See https://github.com/chaijs/chai/issues/86: this makes
        // `whatever.should = someValue` actually set `someValue`, which is
        // especially useful for `global.should = require('chai').should()`.
        //
        // Note that we have to use [[DefineProperty]] instead of [[Put]]
        // since otherwise we would trigger this very setter!
        Object.defineProperty(this, 'should', {
          value: value,
          enumerable: true,
          configurable: true,
          writable: true
        });
      }
      // modify Object.prototype to have `should`
      Object.defineProperty(Object.prototype, 'should', {
        set: shouldSetter
        , get: shouldGetter
        , configurable: true
      });
  
      var should = {};
  
      /**
       * ### .fail(actual, expected, [message], [operator])
       *
       * Throw a failure.
       *
       * @name fail
       * @param {Mixed} actual
       * @param {Mixed} expected
       * @param {String} message
       * @param {String} operator
       * @api public
       */
  
      should.fail = function (actual, expected, message, operator) {
        message = message || 'should.fail()';
        throw new chai.AssertionError(message, {
            actual: actual
          , expected: expected
          , operator: operator
        }, should.fail);
      };
  
      should.equal = function (val1, val2, msg) {
        new Assertion(val1, msg).to.equal(val2);
      };
  
      should.Throw = function (fn, errt, errs, msg) {
        new Assertion(fn, msg).to.Throw(errt, errs);
      };
  
      should.exist = function (val, msg) {
        new Assertion(val, msg).to.exist;
      }
  
      // negation
      should.not = {}
  
      should.not.equal = function (val1, val2, msg) {
        new Assertion(val1, msg).to.not.equal(val2);
      };
  
      should.not.Throw = function (fn, errt, errs, msg) {
        new Assertion(fn, msg).to.not.Throw(errt, errs);
      };
  
      should.not.exist = function (val, msg) {
        new Assertion(val, msg).to.not.exist;
      }
  
      should['throw'] = should['Throw'];
      should.not['throw'] = should.not['Throw'];
  
      return should;
    };
  
    chai.should = loadShould;
    chai.Should = loadShould;
  };
  
  },{}],64:[function(require,module,exports){
  /*!
   * Chai - addChainingMethod utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /*!
   * Module dependencies
   */
  
  var transferFlags = require('./transferFlags');
  var flag = require('./flag');
  var config = require('../config');
  
  /*!
   * Module variables
   */
  
  // Check whether `__proto__` is supported
  var hasProtoSupport = '__proto__' in Object;
  
  // Without `__proto__` support, this module will need to add properties to a function.
  // However, some Function.prototype methods cannot be overwritten,
  // and there seems no easy cross-platform way to detect them (@see chaijs/chai/issues/69).
  var excludeNames = /^(?:length|name|arguments|caller)$/;
  
  // Cache `Function` properties
  var call  = Function.prototype.call,
      apply = Function.prototype.apply;
  
  /**
   * ### addChainableMethod (ctx, name, method, chainingBehavior)
   *
   * Adds a method to an object, such that the method can also be chained.
   *
   *     utils.addChainableMethod(chai.Assertion.prototype, 'foo', function (str) {
   *       var obj = utils.flag(this, 'object');
   *       new chai.Assertion(obj).to.be.equal(str);
   *     });
   *
   * Can also be accessed directly from `chai.Assertion`.
   *
   *     chai.Assertion.addChainableMethod('foo', fn, chainingBehavior);
   *
   * The result can then be used as both a method assertion, executing both `method` and
   * `chainingBehavior`, or as a language chain, which only executes `chainingBehavior`.
   *
   *     expect(fooStr).to.be.foo('bar');
   *     expect(fooStr).to.be.foo.equal('foo');
   *
   * @param {Object} ctx object to which the method is added
   * @param {String} name of method to add
   * @param {Function} method function to be used for `name`, when called
   * @param {Function} chainingBehavior function to be called every time the property is accessed
   * @name addChainableMethod
   * @api public
   */
  
  module.exports = function (ctx, name, method, chainingBehavior) {
    if (typeof chainingBehavior !== 'function') {
      chainingBehavior = function () { };
    }
  
    var chainableBehavior = {
        method: method
      , chainingBehavior: chainingBehavior
    };
  
    // save the methods so we can overwrite them later, if we need to.
    if (!ctx.__methods) {
      ctx.__methods = {};
    }
    ctx.__methods[name] = chainableBehavior;
  
    Object.defineProperty(ctx, name,
      { get: function () {
          chainableBehavior.chainingBehavior.call(this);
  
          var assert = function assert() {
            var old_ssfi = flag(this, 'ssfi');
            if (old_ssfi && config.includeStack === false)
              flag(this, 'ssfi', assert);
            var result = chainableBehavior.method.apply(this, arguments);
            return result === undefined ? this : result;
          };
  
          // Use `__proto__` if available
          if (hasProtoSupport) {
            // Inherit all properties from the object by replacing the `Function` prototype
            var prototype = assert.__proto__ = Object.create(this);
            // Restore the `call` and `apply` methods from `Function`
            prototype.call = call;
            prototype.apply = apply;
          }
          // Otherwise, redefine all properties (slow!)
          else {
            var asserterNames = Object.getOwnPropertyNames(ctx);
            asserterNames.forEach(function (asserterName) {
              if (!excludeNames.test(asserterName)) {
                var pd = Object.getOwnPropertyDescriptor(ctx, asserterName);
                Object.defineProperty(assert, asserterName, pd);
              }
            });
          }
  
          transferFlags(this, assert);
          return assert;
        }
      , configurable: true
    });
  };
  
  },{"../config":59,"./flag":68,"./transferFlags":84}],65:[function(require,module,exports){
  /*!
   * Chai - addMethod utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  var config = require('../config');
  
  /**
   * ### .addMethod (ctx, name, method)
   *
   * Adds a method to the prototype of an object.
   *
   *     utils.addMethod(chai.Assertion.prototype, 'foo', function (str) {
   *       var obj = utils.flag(this, 'object');
   *       new chai.Assertion(obj).to.be.equal(str);
   *     });
   *
   * Can also be accessed directly from `chai.Assertion`.
   *
   *     chai.Assertion.addMethod('foo', fn);
   *
   * Then can be used as any other assertion.
   *
   *     expect(fooStr).to.be.foo('bar');
   *
   * @param {Object} ctx object to which the method is added
   * @param {String} name of method to add
   * @param {Function} method function to be used for name
   * @name addMethod
   * @api public
   */
  var flag = require('./flag');
  
  module.exports = function (ctx, name, method) {
    ctx[name] = function () {
      var old_ssfi = flag(this, 'ssfi');
      if (old_ssfi && config.includeStack === false)
        flag(this, 'ssfi', ctx[name]);
      var result = method.apply(this, arguments);
      return result === undefined ? this : result;
    };
  };
  
  },{"../config":59,"./flag":68}],66:[function(require,module,exports){
  /*!
   * Chai - addProperty utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  var config = require('../config');
  var flag = require('./flag');
  
  /**
   * ### addProperty (ctx, name, getter)
   *
   * Adds a property to the prototype of an object.
   *
   *     utils.addProperty(chai.Assertion.prototype, 'foo', function () {
   *       var obj = utils.flag(this, 'object');
   *       new chai.Assertion(obj).to.be.instanceof(Foo);
   *     });
   *
   * Can also be accessed directly from `chai.Assertion`.
   *
   *     chai.Assertion.addProperty('foo', fn);
   *
   * Then can be used as any other assertion.
   *
   *     expect(myFoo).to.be.foo;
   *
   * @param {Object} ctx object to which the property is added
   * @param {String} name of property to add
   * @param {Function} getter function to be used for name
   * @name addProperty
   * @api public
   */
  
  module.exports = function (ctx, name, getter) {
    Object.defineProperty(ctx, name,
      { get: function addProperty() {
          var old_ssfi = flag(this, 'ssfi');
          if (old_ssfi && config.includeStack === false)
            flag(this, 'ssfi', addProperty);
  
          var result = getter.call(this);
          return result === undefined ? this : result;
        }
      , configurable: true
    });
  };
  
  },{"../config":59,"./flag":68}],67:[function(require,module,exports){
  /*!
   * Chai - expectTypes utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * ### expectTypes(obj, types)
   *
   * Ensures that the object being tested against is of a valid type.
   *
   *     utils.expectTypes(this, ['array', 'object', 'string']);
   *
   * @param {Mixed} obj constructed Assertion
   * @param {Array} type A list of allowed types for this assertion
   * @name expectTypes
   * @api public
   */
  
  var AssertionError = require('assertion-error');
  var flag = require('./flag');
  var type = require('type-detect');
  
  module.exports = function (obj, types) {
    var obj = flag(obj, 'object');
    types = types.map(function (t) { return t.toLowerCase(); });
    types.sort();
  
    // Transforms ['lorem', 'ipsum'] into 'a lirum, or an ipsum'
    var str = types.map(function (t, index) {
      var art = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(t.charAt(0)) ? 'an' : 'a';
      var or = types.length > 1 && index === types.length - 1 ? 'or ' : '';
      return or + art + ' ' + t;
    }).join(', ');
  
    if (!types.some(function (expected) { return type(obj) === expected; })) {
      throw new AssertionError(
        'object tested must be ' + str + ', but ' + type(obj) + ' given'
      );
    }
  };
  
  },{"./flag":68,"assertion-error":85,"type-detect":90}],68:[function(require,module,exports){
  /*!
   * Chai - flag utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * ### flag(object, key, [value])
   *
   * Get or set a flag value on an object. If a
   * value is provided it will be set, else it will
   * return the currently set value or `undefined` if
   * the value is not set.
   *
   *     utils.flag(this, 'foo', 'bar'); // setter
   *     utils.flag(this, 'foo'); // getter, returns `bar`
   *
   * @param {Object} object constructed Assertion
   * @param {String} key
   * @param {Mixed} value (optional)
   * @name flag
   * @api private
   */
  
  module.exports = function (obj, key, value) {
    var flags = obj.__flags || (obj.__flags = Object.create(null));
    if (arguments.length === 3) {
      flags[key] = value;
    } else {
      return flags[key];
    }
  };
  
  },{}],69:[function(require,module,exports){
  /*!
   * Chai - getActual utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * # getActual(object, [actual])
   *
   * Returns the `actual` value for an Assertion
   *
   * @param {Object} object (constructed Assertion)
   * @param {Arguments} chai.Assertion.prototype.assert arguments
   */
  
  module.exports = function (obj, args) {
    return args.length > 4 ? args[4] : obj._obj;
  };
  
  },{}],70:[function(require,module,exports){
  /*!
   * Chai - getEnumerableProperties utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * ### .getEnumerableProperties(object)
   *
   * This allows the retrieval of enumerable property names of an object,
   * inherited or not.
   *
   * @param {Object} object
   * @returns {Array}
   * @name getEnumerableProperties
   * @api public
   */
  
  module.exports = function getEnumerableProperties(object) {
    var result = [];
    for (var name in object) {
      result.push(name);
    }
    return result;
  };
  
  },{}],71:[function(require,module,exports){
  /*!
   * Chai - message composition utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /*!
   * Module dependancies
   */
  
  var flag = require('./flag')
    , getActual = require('./getActual')
    , inspect = require('./inspect')
    , objDisplay = require('./objDisplay');
  
  /**
   * ### .getMessage(object, message, negateMessage)
   *
   * Construct the error message based on flags
   * and template tags. Template tags will return
   * a stringified inspection of the object referenced.
   *
   * Message template tags:
   * - `#{this}` current asserted object
   * - `#{act}` actual value
   * - `#{exp}` expected value
   *
   * @param {Object} object (constructed Assertion)
   * @param {Arguments} chai.Assertion.prototype.assert arguments
   * @name getMessage
   * @api public
   */
  
  module.exports = function (obj, args) {
    var negate = flag(obj, 'negate')
      , val = flag(obj, 'object')
      , expected = args[3]
      , actual = getActual(obj, args)
      , msg = negate ? args[2] : args[1]
      , flagMsg = flag(obj, 'message');
  
    if(typeof msg === "function") msg = msg();
    msg = msg || '';
    msg = msg
      .replace(/#{this}/g, objDisplay(val))
      .replace(/#{act}/g, objDisplay(actual))
      .replace(/#{exp}/g, objDisplay(expected));
  
    return flagMsg ? flagMsg + ': ' + msg : msg;
  };
  
  },{"./flag":68,"./getActual":69,"./inspect":78,"./objDisplay":79}],72:[function(require,module,exports){
  /*!
   * Chai - getName utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * # getName(func)
   *
   * Gets the name of a function, in a cross-browser way.
   *
   * @param {Function} a function (usually a constructor)
   */
  
  module.exports = function (func) {
    if (func.name) return func.name;
  
    var match = /^\s?function ([^(]*)\(/.exec(func);
    return match && match[1] ? match[1] : "";
  };
  
  },{}],73:[function(require,module,exports){
  /*!
   * Chai - getPathInfo utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  var hasProperty = require('./hasProperty');
  
  /**
   * ### .getPathInfo(path, object)
   *
   * This allows the retrieval of property info in an
   * object given a string path.
   *
   * The path info consists of an object with the
   * following properties:
   *
   * * parent - The parent object of the property referenced by `path`
   * * name - The name of the final property, a number if it was an array indexer
   * * value - The value of the property, if it exists, otherwise `undefined`
   * * exists - Whether the property exists or not
   *
   * @param {String} path
   * @param {Object} object
   * @returns {Object} info
   * @name getPathInfo
   * @api public
   */
  
  module.exports = function getPathInfo(path, obj) {
    var parsed = parsePath(path),
        last = parsed[parsed.length - 1];
  
    var info = {
      parent: parsed.length > 1 ? _getPathValue(parsed, obj, parsed.length - 1) : obj,
      name: last.p || last.i,
      value: _getPathValue(parsed, obj)
    };
    info.exists = hasProperty(info.name, info.parent);
  
    return info;
  };
  
  
  /*!
   * ## parsePath(path)
   *
   * Helper function used to parse string object
   * paths. Use in conjunction with `_getPathValue`.
   *
   *      var parsed = parsePath('myobject.property.subprop');
   *
   * ### Paths:
   *
   * * Can be as near infinitely deep and nested
   * * Arrays are also valid using the formal `myobject.document[3].property`.
   * * Literal dots and brackets (not delimiter) must be backslash-escaped.
   *
   * @param {String} path
   * @returns {Object} parsed
   * @api private
   */
  
  function parsePath (path) {
    var str = path.replace(/([^\\])\[/g, '$1.[')
      , parts = str.match(/(\\\.|[^.]+?)+/g);
    return parts.map(function (value) {
      var re = /^\[(\d+)\]$/
        , mArr = re.exec(value);
      if (mArr) return { i: parseFloat(mArr[1]) };
      else return { p: value.replace(/\\([.\[\]])/g, '$1') };
    });
  }
  
  
  /*!
   * ## _getPathValue(parsed, obj)
   *
   * Helper companion function for `.parsePath` that returns
   * the value located at the parsed address.
   *
   *      var value = getPathValue(parsed, obj);
   *
   * @param {Object} parsed definition from `parsePath`.
   * @param {Object} object to search against
   * @param {Number} object to search against
   * @returns {Object|Undefined} value
   * @api private
   */
  
  function _getPathValue (parsed, obj, index) {
    var tmp = obj
      , res;
  
    index = (index === undefined ? parsed.length : index);
  
    for (var i = 0, l = index; i < l; i++) {
      var part = parsed[i];
      if (tmp) {
        if ('undefined' !== typeof part.p)
          tmp = tmp[part.p];
        else if ('undefined' !== typeof part.i)
          tmp = tmp[part.i];
        if (i == (l - 1)) res = tmp;
      } else {
        res = undefined;
      }
    }
    return res;
  }
  
  },{"./hasProperty":76}],74:[function(require,module,exports){
  /*!
   * Chai - getPathValue utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * @see https://github.com/logicalparadox/filtr
   * MIT Licensed
   */
  
  var getPathInfo = require('./getPathInfo');
  
  /**
   * ### .getPathValue(path, object)
   *
   * This allows the retrieval of values in an
   * object given a string path.
   *
   *     var obj = {
   *         prop1: {
   *             arr: ['a', 'b', 'c']
   *           , str: 'Hello'
   *         }
   *       , prop2: {
   *             arr: [ { nested: 'Universe' } ]
   *           , str: 'Hello again!'
   *         }
   *     }
   *
   * The following would be the results.
   *
   *     getPathValue('prop1.str', obj); // Hello
   *     getPathValue('prop1.att[2]', obj); // b
   *     getPathValue('prop2.arr[0].nested', obj); // Universe
   *
   * @param {String} path
   * @param {Object} object
   * @returns {Object} value or `undefined`
   * @name getPathValue
   * @api public
   */
  module.exports = function(path, obj) {
    var info = getPathInfo(path, obj);
    return info.value;
  }; 
  
  },{"./getPathInfo":73}],75:[function(require,module,exports){
  /*!
   * Chai - getProperties utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * ### .getProperties(object)
   *
   * This allows the retrieval of property names of an object, enumerable or not,
   * inherited or not.
   *
   * @param {Object} object
   * @returns {Array}
   * @name getProperties
   * @api public
   */
  
  module.exports = function getProperties(object) {
    var result = Object.getOwnPropertyNames(object);
  
    function addProperty(property) {
      if (result.indexOf(property) === -1) {
        result.push(property);
      }
    }
  
    var proto = Object.getPrototypeOf(object);
    while (proto !== null) {
      Object.getOwnPropertyNames(proto).forEach(addProperty);
      proto = Object.getPrototypeOf(proto);
    }
  
    return result;
  };
  
  },{}],76:[function(require,module,exports){
  /*!
   * Chai - hasProperty utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  var type = require('type-detect');
  
  /**
   * ### .hasProperty(object, name)
   *
   * This allows checking whether an object has
   * named property or numeric array index.
   *
   * Basically does the same thing as the `in`
   * operator but works properly with natives
   * and null/undefined values.
   *
   *     var obj = {
   *         arr: ['a', 'b', 'c']
   *       , str: 'Hello'
   *     }
   *
   * The following would be the results.
   *
   *     hasProperty('str', obj);  // true
   *     hasProperty('constructor', obj);  // true
   *     hasProperty('bar', obj);  // false
   *     
   *     hasProperty('length', obj.str); // true
   *     hasProperty(1, obj.str);  // true
   *     hasProperty(5, obj.str);  // false
   *
   *     hasProperty('length', obj.arr);  // true
   *     hasProperty(2, obj.arr);  // true
   *     hasProperty(3, obj.arr);  // false
   *
   * @param {Objuect} object
   * @param {String|Number} name
   * @returns {Boolean} whether it exists
   * @name getPathInfo
   * @api public
   */
  
  var literals = {
      'number': Number
    , 'string': String
  };
  
  module.exports = function hasProperty(name, obj) {
    var ot = type(obj);
  
    // Bad Object, obviously no props at all
    if(ot === 'null' || ot === 'undefined')
      return false;
  
    // The `in` operator does not work with certain literals
    // box these before the check
    if(literals[ot] && typeof obj !== 'object')
      obj = new literals[ot](obj);
  
    return name in obj;
  };
  
  },{"type-detect":90}],77:[function(require,module,exports){
  /*!
   * chai
   * Copyright(c) 2011 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /*!
   * Main exports
   */
  
  var exports = module.exports = {};
  
  /*!
   * test utility
   */
  
  exports.test = require('./test');
  
  /*!
   * type utility
   */
  
  exports.type = require('type-detect');
  
  /*!
   * expectTypes utility
   */
  exports.expectTypes = require('./expectTypes');
  
  /*!
   * message utility
   */
  
  exports.getMessage = require('./getMessage');
  
  /*!
   * actual utility
   */
  
  exports.getActual = require('./getActual');
  
  /*!
   * Inspect util
   */
  
  exports.inspect = require('./inspect');
  
  /*!
   * Object Display util
   */
  
  exports.objDisplay = require('./objDisplay');
  
  /*!
   * Flag utility
   */
  
  exports.flag = require('./flag');
  
  /*!
   * Flag transferring utility
   */
  
  exports.transferFlags = require('./transferFlags');
  
  /*!
   * Deep equal utility
   */
  
  exports.eql = require('deep-eql');
  
  /*!
   * Deep path value
   */
  
  exports.getPathValue = require('./getPathValue');
  
  /*!
   * Deep path info
   */
  
  exports.getPathInfo = require('./getPathInfo');
  
  /*!
   * Check if a property exists
   */
  
  exports.hasProperty = require('./hasProperty');
  
  /*!
   * Function name
   */
  
  exports.getName = require('./getName');
  
  /*!
   * add Property
   */
  
  exports.addProperty = require('./addProperty');
  
  /*!
   * add Method
   */
  
  exports.addMethod = require('./addMethod');
  
  /*!
   * overwrite Property
   */
  
  exports.overwriteProperty = require('./overwriteProperty');
  
  /*!
   * overwrite Method
   */
  
  exports.overwriteMethod = require('./overwriteMethod');
  
  /*!
   * Add a chainable method
   */
  
  exports.addChainableMethod = require('./addChainableMethod');
  
  /*!
   * Overwrite chainable method
   */
  
  exports.overwriteChainableMethod = require('./overwriteChainableMethod');
  
  },{"./addChainableMethod":64,"./addMethod":65,"./addProperty":66,"./expectTypes":67,"./flag":68,"./getActual":69,"./getMessage":71,"./getName":72,"./getPathInfo":73,"./getPathValue":74,"./hasProperty":76,"./inspect":78,"./objDisplay":79,"./overwriteChainableMethod":80,"./overwriteMethod":81,"./overwriteProperty":82,"./test":83,"./transferFlags":84,"deep-eql":86,"type-detect":90}],78:[function(require,module,exports){
  // This is (almost) directly from Node.js utils
  // https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/util.js
  
  var getName = require('./getName');
  var getProperties = require('./getProperties');
  var getEnumerableProperties = require('./getEnumerableProperties');
  
  module.exports = inspect;
  
  /**
   * Echos the value of a value. Trys to print the value out
   * in the best way possible given the different types.
   *
   * @param {Object} obj The object to print out.
   * @param {Boolean} showHidden Flag that shows hidden (not enumerable)
   *    properties of objects.
   * @param {Number} depth Depth in which to descend in object. Default is 2.
   * @param {Boolean} colors Flag to turn on ANSI escape codes to color the
   *    output. Default is false (no coloring).
   */
  function inspect(obj, showHidden, depth, colors) {
    var ctx = {
      showHidden: showHidden,
      seen: [],
      stylize: function (str) { return str; }
    };
    return formatValue(ctx, obj, (typeof depth === 'undefined' ? 2 : depth));
  }
  
  // Returns true if object is a DOM element.
  var isDOMElement = function (object) {
    if (typeof HTMLElement === 'object') {
      return object instanceof HTMLElement;
    } else {
      return object &&
        typeof object === 'object' &&
        object.nodeType === 1 &&
        typeof object.nodeName === 'string';
    }
  };
  
  function formatValue(ctx, value, recurseTimes) {
    // Provide a hook for user-specified inspect functions.
    // Check that value is an object with an inspect function on it
    if (value && typeof value.inspect === 'function' &&
        // Filter out the util module, it's inspect function is special
        value.inspect !== exports.inspect &&
        // Also filter out any prototype objects using the circular check.
        !(value.constructor && value.constructor.prototype === value)) {
      var ret = value.inspect(recurseTimes);
      if (typeof ret !== 'string') {
        ret = formatValue(ctx, ret, recurseTimes);
      }
      return ret;
    }
  
    // Primitive types cannot have properties
    var primitive = formatPrimitive(ctx, value);
    if (primitive) {
      return primitive;
    }
  
    // If this is a DOM element, try to get the outer HTML.
    if (isDOMElement(value)) {
      if ('outerHTML' in value) {
        return value.outerHTML;
        // This value does not have an outerHTML attribute,
        //   it could still be an XML element
      } else {
        // Attempt to serialize it
        try {
          if (document.xmlVersion) {
            var xmlSerializer = new XMLSerializer();
            return xmlSerializer.serializeToString(value);
          } else {
            // Firefox 11- do not support outerHTML
            //   It does, however, support innerHTML
            //   Use the following to render the element
            var ns = "http://www.w3.org/1999/xhtml";
            var container = document.createElementNS(ns, '_');
  
            container.appendChild(value.cloneNode(false));
            html = container.innerHTML
              .replace('><', '>' + value.innerHTML + '<');
            container.innerHTML = '';
            return html;
          }
        } catch (err) {
          // This could be a non-native DOM implementation,
          //   continue with the normal flow:
          //   printing the element as if it is an object.
        }
      }
    }
  
    // Look up the keys of the object.
    var visibleKeys = getEnumerableProperties(value);
    var keys = ctx.showHidden ? getProperties(value) : visibleKeys;
  
    // Some type of object without properties can be shortcutted.
    // In IE, errors have a single `stack` property, or if they are vanilla `Error`,
    // a `stack` plus `description` property; ignore those for consistency.
    if (keys.length === 0 || (isError(value) && (
        (keys.length === 1 && keys[0] === 'stack') ||
        (keys.length === 2 && keys[0] === 'description' && keys[1] === 'stack')
       ))) {
      if (typeof value === 'function') {
        var name = getName(value);
        var nameSuffix = name ? ': ' + name : '';
        return ctx.stylize('[Function' + nameSuffix + ']', 'special');
      }
      if (isRegExp(value)) {
        return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
      }
      if (isDate(value)) {
        return ctx.stylize(Date.prototype.toUTCString.call(value), 'date');
      }
      if (isError(value)) {
        return formatError(value);
      }
    }
  
    var base = '', array = false, braces = ['{', '}'];
  
    // Make Array say that they are Array
    if (isArray(value)) {
      array = true;
      braces = ['[', ']'];
    }
  
    // Make functions say that they are functions
    if (typeof value === 'function') {
      var name = getName(value);
      var nameSuffix = name ? ': ' + name : '';
      base = ' [Function' + nameSuffix + ']';
    }
  
    // Make RegExps say that they are RegExps
    if (isRegExp(value)) {
      base = ' ' + RegExp.prototype.toString.call(value);
    }
  
    // Make dates with properties first say the date
    if (isDate(value)) {
      base = ' ' + Date.prototype.toUTCString.call(value);
    }
  
    // Make error with message first say the error
    if (isError(value)) {
      return formatError(value);
    }
  
    if (keys.length === 0 && (!array || value.length == 0)) {
      return braces[0] + base + braces[1];
    }
  
    if (recurseTimes < 0) {
      if (isRegExp(value)) {
        return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
      } else {
        return ctx.stylize('[Object]', 'special');
      }
    }
  
    ctx.seen.push(value);
  
    var output;
    if (array) {
      output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
    } else {
      output = keys.map(function(key) {
        return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
      });
    }
  
    ctx.seen.pop();
  
    return reduceToSingleString(output, base, braces);
  }
  
  
  function formatPrimitive(ctx, value) {
    switch (typeof value) {
      case 'undefined':
        return ctx.stylize('undefined', 'undefined');
  
      case 'string':
        var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
                                                 .replace(/'/g, "\\'")
                                                 .replace(/\\"/g, '"') + '\'';
        return ctx.stylize(simple, 'string');
  
      case 'number':
        if (value === 0 && (1/value) === -Infinity) {
          return ctx.stylize('-0', 'number');
        }
        return ctx.stylize('' + value, 'number');
  
      case 'boolean':
        return ctx.stylize('' + value, 'boolean');
    }
    // For some reason typeof null is "object", so special case here.
    if (value === null) {
      return ctx.stylize('null', 'null');
    }
  }
  
  
  function formatError(value) {
    return '[' + Error.prototype.toString.call(value) + ']';
  }
  
  
  function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
    var output = [];
    for (var i = 0, l = value.length; i < l; ++i) {
      if (Object.prototype.hasOwnProperty.call(value, String(i))) {
        output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
            String(i), true));
      } else {
        output.push('');
      }
    }
    keys.forEach(function(key) {
      if (!key.match(/^\d+$/)) {
        output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
            key, true));
      }
    });
    return output;
  }
  
  
  function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
    var name, str;
    if (value.__lookupGetter__) {
      if (value.__lookupGetter__(key)) {
        if (value.__lookupSetter__(key)) {
          str = ctx.stylize('[Getter/Setter]', 'special');
        } else {
          str = ctx.stylize('[Getter]', 'special');
        }
      } else {
        if (value.__lookupSetter__(key)) {
          str = ctx.stylize('[Setter]', 'special');
        }
      }
    }
    if (visibleKeys.indexOf(key) < 0) {
      name = '[' + key + ']';
    }
    if (!str) {
      if (ctx.seen.indexOf(value[key]) < 0) {
        if (recurseTimes === null) {
          str = formatValue(ctx, value[key], null);
        } else {
          str = formatValue(ctx, value[key], recurseTimes - 1);
        }
        if (str.indexOf('\n') > -1) {
          if (array) {
            str = str.split('\n').map(function(line) {
              return '  ' + line;
            }).join('\n').substr(2);
          } else {
            str = '\n' + str.split('\n').map(function(line) {
              return '   ' + line;
            }).join('\n');
          }
        }
      } else {
        str = ctx.stylize('[Circular]', 'special');
      }
    }
    if (typeof name === 'undefined') {
      if (array && key.match(/^\d+$/)) {
        return str;
      }
      name = JSON.stringify('' + key);
      if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
        name = name.substr(1, name.length - 2);
        name = ctx.stylize(name, 'name');
      } else {
        name = name.replace(/'/g, "\\'")
                   .replace(/\\"/g, '"')
                   .replace(/(^"|"$)/g, "'");
        name = ctx.stylize(name, 'string');
      }
    }
  
    return name + ': ' + str;
  }
  
  
  function reduceToSingleString(output, base, braces) {
    var numLinesEst = 0;
    var length = output.reduce(function(prev, cur) {
      numLinesEst++;
      if (cur.indexOf('\n') >= 0) numLinesEst++;
      return prev + cur.length + 1;
    }, 0);
  
    if (length > 60) {
      return braces[0] +
             (base === '' ? '' : base + '\n ') +
             ' ' +
             output.join(',\n  ') +
             ' ' +
             braces[1];
    }
  
    return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
  }
  
  function isArray(ar) {
    return Array.isArray(ar) ||
           (typeof ar === 'object' && objectToString(ar) === '[object Array]');
  }
  
  function isRegExp(re) {
    return typeof re === 'object' && objectToString(re) === '[object RegExp]';
  }
  
  function isDate(d) {
    return typeof d === 'object' && objectToString(d) === '[object Date]';
  }
  
  function isError(e) {
    return typeof e === 'object' && objectToString(e) === '[object Error]';
  }
  
  function objectToString(o) {
    return Object.prototype.toString.call(o);
  }
  
  },{"./getEnumerableProperties":70,"./getName":72,"./getProperties":75}],79:[function(require,module,exports){
  /*!
   * Chai - flag utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /*!
   * Module dependancies
   */
  
  var inspect = require('./inspect');
  var config = require('../config');
  
  /**
   * ### .objDisplay (object)
   *
   * Determines if an object or an array matches
   * criteria to be inspected in-line for error
   * messages or should be truncated.
   *
   * @param {Mixed} javascript object to inspect
   * @name objDisplay
   * @api public
   */
  
  module.exports = function (obj) {
    var str = inspect(obj)
      , type = Object.prototype.toString.call(obj);
  
    if (config.truncateThreshold && str.length >= config.truncateThreshold) {
      if (type === '[object Function]') {
        return !obj.name || obj.name === ''
          ? '[Function]'
          : '[Function: ' + obj.name + ']';
      } else if (type === '[object Array]') {
        return '[ Array(' + obj.length + ') ]';
      } else if (type === '[object Object]') {
        var keys = Object.keys(obj)
          , kstr = keys.length > 2
            ? keys.splice(0, 2).join(', ') + ', ...'
            : keys.join(', ');
        return '{ Object (' + kstr + ') }';
      } else {
        return str;
      }
    } else {
      return str;
    }
  };
  
  },{"../config":59,"./inspect":78}],80:[function(require,module,exports){
  /*!
   * Chai - overwriteChainableMethod utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * ### overwriteChainableMethod (ctx, name, method, chainingBehavior)
   *
   * Overwites an already existing chainable method
   * and provides access to the previous function or
   * property.  Must return functions to be used for
   * name.
   *
   *     utils.overwriteChainableMethod(chai.Assertion.prototype, 'length',
   *       function (_super) {
   *       }
   *     , function (_super) {
   *       }
   *     );
   *
   * Can also be accessed directly from `chai.Assertion`.
   *
   *     chai.Assertion.overwriteChainableMethod('foo', fn, fn);
   *
   * Then can be used as any other assertion.
   *
   *     expect(myFoo).to.have.length(3);
   *     expect(myFoo).to.have.length.above(3);
   *
   * @param {Object} ctx object whose method / property is to be overwritten
   * @param {String} name of method / property to overwrite
   * @param {Function} method function that returns a function to be used for name
   * @param {Function} chainingBehavior function that returns a function to be used for property
   * @name overwriteChainableMethod
   * @api public
   */
  
  module.exports = function (ctx, name, method, chainingBehavior) {
    var chainableBehavior = ctx.__methods[name];
  
    var _chainingBehavior = chainableBehavior.chainingBehavior;
    chainableBehavior.chainingBehavior = function () {
      var result = chainingBehavior(_chainingBehavior).call(this);
      return result === undefined ? this : result;
    };
  
    var _method = chainableBehavior.method;
    chainableBehavior.method = function () {
      var result = method(_method).apply(this, arguments);
      return result === undefined ? this : result;
    };
  };
  
  },{}],81:[function(require,module,exports){
  /*!
   * Chai - overwriteMethod utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * ### overwriteMethod (ctx, name, fn)
   *
   * Overwites an already existing method and provides
   * access to previous function. Must return function
   * to be used for name.
   *
   *     utils.overwriteMethod(chai.Assertion.prototype, 'equal', function (_super) {
   *       return function (str) {
   *         var obj = utils.flag(this, 'object');
   *         if (obj instanceof Foo) {
   *           new chai.Assertion(obj.value).to.equal(str);
   *         } else {
   *           _super.apply(this, arguments);
   *         }
   *       }
   *     });
   *
   * Can also be accessed directly from `chai.Assertion`.
   *
   *     chai.Assertion.overwriteMethod('foo', fn);
   *
   * Then can be used as any other assertion.
   *
   *     expect(myFoo).to.equal('bar');
   *
   * @param {Object} ctx object whose method is to be overwritten
   * @param {String} name of method to overwrite
   * @param {Function} method function that returns a function to be used for name
   * @name overwriteMethod
   * @api public
   */
  
  module.exports = function (ctx, name, method) {
    var _method = ctx[name]
      , _super = function () { return this; };
  
    if (_method && 'function' === typeof _method)
      _super = _method;
  
    ctx[name] = function () {
      var result = method(_super).apply(this, arguments);
      return result === undefined ? this : result;
    }
  };
  
  },{}],82:[function(require,module,exports){
  /*!
   * Chai - overwriteProperty utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * ### overwriteProperty (ctx, name, fn)
   *
   * Overwites an already existing property getter and provides
   * access to previous value. Must return function to use as getter.
   *
   *     utils.overwriteProperty(chai.Assertion.prototype, 'ok', function (_super) {
   *       return function () {
   *         var obj = utils.flag(this, 'object');
   *         if (obj instanceof Foo) {
   *           new chai.Assertion(obj.name).to.equal('bar');
   *         } else {
   *           _super.call(this);
   *         }
   *       }
   *     });
   *
   *
   * Can also be accessed directly from `chai.Assertion`.
   *
   *     chai.Assertion.overwriteProperty('foo', fn);
   *
   * Then can be used as any other assertion.
   *
   *     expect(myFoo).to.be.ok;
   *
   * @param {Object} ctx object whose property is to be overwritten
   * @param {String} name of property to overwrite
   * @param {Function} getter function that returns a getter function to be used for name
   * @name overwriteProperty
   * @api public
   */
  
  module.exports = function (ctx, name, getter) {
    var _get = Object.getOwnPropertyDescriptor(ctx, name)
      , _super = function () {};
  
    if (_get && 'function' === typeof _get.get)
      _super = _get.get
  
    Object.defineProperty(ctx, name,
      { get: function () {
          var result = getter(_super).call(this);
          return result === undefined ? this : result;
        }
      , configurable: true
    });
  };
  
  },{}],83:[function(require,module,exports){
  /*!
   * Chai - test utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /*!
   * Module dependancies
   */
  
  var flag = require('./flag');
  
  /**
   * # test(object, expression)
   *
   * Test and object for expression.
   *
   * @param {Object} object (constructed Assertion)
   * @param {Arguments} chai.Assertion.prototype.assert arguments
   */
  
  module.exports = function (obj, args) {
    var negate = flag(obj, 'negate')
      , expr = args[0];
    return negate ? !expr : expr;
  };
  
  },{"./flag":68}],84:[function(require,module,exports){
  /*!
   * Chai - transferFlags utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * ### transferFlags(assertion, object, includeAll = true)
   *
   * Transfer all the flags for `assertion` to `object`. If
   * `includeAll` is set to `false`, then the base Chai
   * assertion flags (namely `object`, `ssfi`, and `message`)
   * will not be transferred.
   *
   *
   *     var newAssertion = new Assertion();
   *     utils.transferFlags(assertion, newAssertion);
   *
   *     var anotherAsseriton = new Assertion(myObj);
   *     utils.transferFlags(assertion, anotherAssertion, false);
   *
   * @param {Assertion} assertion the assertion to transfer the flags from
   * @param {Object} object the object to transfer the flags to; usually a new assertion
   * @param {Boolean} includeAll
   * @name transferFlags
   * @api private
   */
  
  module.exports = function (assertion, object, includeAll) {
    var flags = assertion.__flags || (assertion.__flags = Object.create(null));
  
    if (!object.__flags) {
      object.__flags = Object.create(null);
    }
  
    includeAll = arguments.length === 3 ? includeAll : true;
  
    for (var flag in flags) {
      if (includeAll ||
          (flag !== 'object' && flag !== 'ssfi' && flag != 'message')) {
        object.__flags[flag] = flags[flag];
      }
    }
  };
  
  },{}],85:[function(require,module,exports){
  /*!
   * assertion-error
   * Copyright(c) 2013 Jake Luer <jake@qualiancy.com>
   * MIT Licensed
   */
  
  /*!
   * Return a function that will copy properties from
   * one object to another excluding any originally
   * listed. Returned function will create a new `{}`.
   *
   * @param {String} excluded properties ...
   * @return {Function}
   */
  
  function exclude () {
    var excludes = [].slice.call(arguments);
  
    function excludeProps (res, obj) {
      Object.keys(obj).forEach(function (key) {
        if (!~excludes.indexOf(key)) res[key] = obj[key];
      });
    }
  
    return function extendExclude () {
      var args = [].slice.call(arguments)
        , i = 0
        , res = {};
  
      for (; i < args.length; i++) {
        excludeProps(res, args[i]);
      }
  
      return res;
    };
  };
  
  /*!
   * Primary Exports
   */
  
  module.exports = AssertionError;
  
  /**
   * ### AssertionError
   *
   * An extension of the JavaScript `Error` constructor for
   * assertion and validation scenarios.
   *
   * @param {String} message
   * @param {Object} properties to include (optional)
   * @param {callee} start stack function (optional)
   */
  
  function AssertionError (message, _props, ssf) {
    var extend = exclude('name', 'message', 'stack', 'constructor', 'toJSON')
      , props = extend(_props || {});
  
    // default values
    this.message = message || 'Unspecified AssertionError';
    this.showDiff = false;
  
    // copy from properties
    for (var key in props) {
      this[key] = props[key];
    }
  
    // capture stack trace
    ssf = ssf || arguments.callee;
    if (ssf && Error.captureStackTrace) {
      Error.captureStackTrace(this, ssf);
    } else {
      this.stack = new Error().stack;
    }
  }
  
  /*!
   * Inherit from Error.prototype
   */
  
  AssertionError.prototype = Object.create(Error.prototype);
  
  /*!
   * Statically set name
   */
  
  AssertionError.prototype.name = 'AssertionError';
  
  /*!
   * Ensure correct constructor
   */
  
  AssertionError.prototype.constructor = AssertionError;
  
  /**
   * Allow errors to be converted to JSON for static transfer.
   *
   * @param {Boolean} include stack (default: `true`)
   * @return {Object} object that can be `JSON.stringify`
   */
  
  AssertionError.prototype.toJSON = function (stack) {
    var extend = exclude('constructor', 'toJSON', 'stack')
      , props = extend({ name: this.name }, this);
  
    // include stack if exists and not turned off
    if (false !== stack && this.stack) {
      props.stack = this.stack;
    }
  
    return props;
  };
  
  },{}],86:[function(require,module,exports){
  module.exports = require('./lib/eql');
  
  },{"./lib/eql":87}],87:[function(require,module,exports){
  /*!
   * deep-eql
   * Copyright(c) 2013 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /*!
   * Module dependencies
   */
  
  var type = require('type-detect');
  
  /*!
   * Buffer.isBuffer browser shim
   */
  
  var Buffer;
  try { Buffer = require('buffer').Buffer; }
  catch(ex) {
    Buffer = {};
    Buffer.isBuffer = function() { return false; }
  }
  
  /*!
   * Primary Export
   */
  
  module.exports = deepEqual;
  
  /**
   * Assert super-strict (egal) equality between
   * two objects of any type.
   *
   * @param {Mixed} a
   * @param {Mixed} b
   * @param {Array} memoised (optional)
   * @return {Boolean} equal match
   */
  
  function deepEqual(a, b, m) {
    if (sameValue(a, b)) {
      return true;
    } else if ('date' === type(a)) {
      return dateEqual(a, b);
    } else if ('regexp' === type(a)) {
      return regexpEqual(a, b);
    } else if (Buffer.isBuffer(a)) {
      return bufferEqual(a, b);
    } else if ('arguments' === type(a)) {
      return argumentsEqual(a, b, m);
    } else if (!typeEqual(a, b)) {
      return false;
    } else if (('object' !== type(a) && 'object' !== type(b))
    && ('array' !== type(a) && 'array' !== type(b))) {
      return sameValue(a, b);
    } else {
      return objectEqual(a, b, m);
    }
  }
  
  /*!
   * Strict (egal) equality test. Ensures that NaN always
   * equals NaN and `-0` does not equal `+0`.
   *
   * @param {Mixed} a
   * @param {Mixed} b
   * @return {Boolean} equal match
   */
  
  function sameValue(a, b) {
    if (a === b) return a !== 0 || 1 / a === 1 / b;
    return a !== a && b !== b;
  }
  
  /*!
   * Compare the types of two given objects and
   * return if they are equal. Note that an Array
   * has a type of `array` (not `object`) and arguments
   * have a type of `arguments` (not `array`/`object`).
   *
   * @param {Mixed} a
   * @param {Mixed} b
   * @return {Boolean} result
   */
  
  function typeEqual(a, b) {
    return type(a) === type(b);
  }
  
  /*!
   * Compare two Date objects by asserting that
   * the time values are equal using `saveValue`.
   *
   * @param {Date} a
   * @param {Date} b
   * @return {Boolean} result
   */
  
  function dateEqual(a, b) {
    if ('date' !== type(b)) return false;
    return sameValue(a.getTime(), b.getTime());
  }
  
  /*!
   * Compare two regular expressions by converting them
   * to string and checking for `sameValue`.
   *
   * @param {RegExp} a
   * @param {RegExp} b
   * @return {Boolean} result
   */
  
  function regexpEqual(a, b) {
    if ('regexp' !== type(b)) return false;
    return sameValue(a.toString(), b.toString());
  }
  
  /*!
   * Assert deep equality of two `arguments` objects.
   * Unfortunately, these must be sliced to arrays
   * prior to test to ensure no bad behavior.
   *
   * @param {Arguments} a
   * @param {Arguments} b
   * @param {Array} memoize (optional)
   * @return {Boolean} result
   */
  
  function argumentsEqual(a, b, m) {
    if ('arguments' !== type(b)) return false;
    a = [].slice.call(a);
    b = [].slice.call(b);
    return deepEqual(a, b, m);
  }
  
  /*!
   * Get enumerable properties of a given object.
   *
   * @param {Object} a
   * @return {Array} property names
   */
  
  function enumerable(a) {
    var res = [];
    for (var key in a) res.push(key);
    return res;
  }
  
  /*!
   * Simple equality for flat iterable objects
   * such as Arrays or Node.js buffers.
   *
   * @param {Iterable} a
   * @param {Iterable} b
   * @return {Boolean} result
   */
  
  function iterableEqual(a, b) {
    if (a.length !==  b.length) return false;
  
    var i = 0;
    var match = true;
  
    for (; i < a.length; i++) {
      if (a[i] !== b[i]) {
        match = false;
        break;
      }
    }
  
    return match;
  }
  
  /*!
   * Extension to `iterableEqual` specifically
   * for Node.js Buffers.
   *
   * @param {Buffer} a
   * @param {Mixed} b
   * @return {Boolean} result
   */
  
  function bufferEqual(a, b) {
    if (!Buffer.isBuffer(b)) return false;
    return iterableEqual(a, b);
  }
  
  /*!
   * Block for `objectEqual` ensuring non-existing
   * values don't get in.
   *
   * @param {Mixed} object
   * @return {Boolean} result
   */
  
  function isValue(a) {
    return a !== null && a !== undefined;
  }
  
  /*!
   * Recursively check the equality of two objects.
   * Once basic sameness has been established it will
   * defer to `deepEqual` for each enumerable key
   * in the object.
   *
   * @param {Mixed} a
   * @param {Mixed} b
   * @return {Boolean} result
   */
  
  function objectEqual(a, b, m) {
    if (!isValue(a) || !isValue(b)) {
      return false;
    }
  
    if (a.prototype !== b.prototype) {
      return false;
    }
  
    var i;
    if (m) {
      for (i = 0; i < m.length; i++) {
        if ((m[i][0] === a && m[i][1] === b)
        ||  (m[i][0] === b && m[i][1] === a)) {
          return true;
        }
      }
    } else {
      m = [];
    }
  
    try {
      var ka = enumerable(a);
      var kb = enumerable(b);
    } catch (ex) {
      return false;
    }
  
    ka.sort();
    kb.sort();
  
    if (!iterableEqual(ka, kb)) {
      return false;
    }
  
    m.push([ a, b ]);
  
    var key;
    for (i = ka.length - 1; i >= 0; i--) {
      key = ka[i];
      if (!deepEqual(a[key], b[key], m)) {
        return false;
      }
    }
  
    return true;
  }
  
  },{"buffer":15,"type-detect":88}],88:[function(require,module,exports){
  module.exports = require('./lib/type');
  
  },{"./lib/type":89}],89:[function(require,module,exports){
  /*!
   * type-detect
   * Copyright(c) 2013 jake luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /*!
   * Primary Exports
   */
  
  var exports = module.exports = getType;
  
  /*!
   * Detectable javascript natives
   */
  
  var natives = {
      '[object Array]': 'array'
    , '[object RegExp]': 'regexp'
    , '[object Function]': 'function'
    , '[object Arguments]': 'arguments'
    , '[object Date]': 'date'
  };
  
  /**
   * ### typeOf (obj)
   *
   * Use several different techniques to determine
   * the type of object being tested.
   *
   *
   * @param {Mixed} object
   * @return {String} object type
   * @api public
   */
  
  function getType (obj) {
    var str = Object.prototype.toString.call(obj);
    if (natives[str]) return natives[str];
    if (obj === null) return 'null';
    if (obj === undefined) return 'undefined';
    if (obj === Object(obj)) return 'object';
    return typeof obj;
  }
  
  exports.Library = Library;
  
  /**
   * ### Library
   *
   * Create a repository for custom type detection.
   *
   * ```js
   * var lib = new type.Library;
   * ```
   *
   */
  
  function Library () {
    this.tests = {};
  }
  
  /**
   * #### .of (obj)
   *
   * Expose replacement `typeof` detection to the library.
   *
   * ```js
   * if ('string' === lib.of('hello world')) {
   *   // ...
   * }
   * ```
   *
   * @param {Mixed} object to test
   * @return {String} type
   */
  
  Library.prototype.of = getType;
  
  /**
   * #### .define (type, test)
   *
   * Add a test to for the `.test()` assertion.
   *
   * Can be defined as a regular expression:
   *
   * ```js
   * lib.define('int', /^[0-9]+$/);
   * ```
   *
   * ... or as a function:
   *
   * ```js
   * lib.define('bln', function (obj) {
   *   if ('boolean' === lib.of(obj)) return true;
   *   var blns = [ 'yes', 'no', 'true', 'false', 1, 0 ];
   *   if ('string' === lib.of(obj)) obj = obj.toLowerCase();
   *   return !! ~blns.indexOf(obj);
   * });
   * ```
   *
   * @param {String} type
   * @param {RegExp|Function} test
   * @api public
   */
  
  Library.prototype.define = function (type, test) {
    if (arguments.length === 1) return this.tests[type];
    this.tests[type] = test;
    return this;
  };
  
  /**
   * #### .test (obj, test)
   *
   * Assert that an object is of type. Will first
   * check natives, and if that does not pass it will
   * use the user defined custom tests.
   *
   * ```js
   * assert(lib.test('1', 'int'));
   * assert(lib.test('yes', 'bln'));
   * ```
   *
   * @param {Mixed} object
   * @param {String} type
   * @return {Boolean} result
   * @api public
   */
  
  Library.prototype.test = function (obj, type) {
    if (type === getType(obj)) return true;
    var test = this.tests[type];
  
    if (test && 'regexp' === getType(test)) {
      return test.test(obj);
    } else if (test && 'function' === getType(test)) {
      return test(obj);
    } else {
      throw new ReferenceError('Type test "' + type + '" not defined or invalid.');
    }
  };
  
  },{}],90:[function(require,module,exports){
  arguments[4][88][0].apply(exports,arguments)
  },{"./lib/type":91,"dup":88}],91:[function(require,module,exports){
  /*!
   * type-detect
   * Copyright(c) 2013 jake luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /*!
   * Primary Exports
   */
  
  var exports = module.exports = getType;
  
  /**
   * ### typeOf (obj)
   *
   * Use several different techniques to determine
   * the type of object being tested.
   *
   *
   * @param {Mixed} object
   * @return {String} object type
   * @api public
   */
  var objectTypeRegexp = /^\[object (.*)\]$/;
  
  function getType(obj) {
    var type = Object.prototype.toString.call(obj).match(objectTypeRegexp)[1].toLowerCase();
    // Let "new String('')" return 'object'
    if (typeof Promise === 'function' && obj instanceof Promise) return 'promise';
    // PhantomJS has type "DOMWindow" for null
    if (obj === null) return 'null';
    // PhantomJS has type "DOMWindow" for undefined
    if (obj === undefined) return 'undefined';
    return type;
  }
  
  exports.Library = Library;
  
  /**
   * ### Library
   *
   * Create a repository for custom type detection.
   *
   * ```js
   * var lib = new type.Library;
   * ```
   *
   */
  
  function Library() {
    if (!(this instanceof Library)) return new Library();
    this.tests = {};
  }
  
  /**
   * #### .of (obj)
   *
   * Expose replacement `typeof` detection to the library.
   *
   * ```js
   * if ('string' === lib.of('hello world')) {
   *   // ...
   * }
   * ```
   *
   * @param {Mixed} object to test
   * @return {String} type
   */
  
  Library.prototype.of = getType;
  
  /**
   * #### .define (type, test)
   *
   * Add a test to for the `.test()` assertion.
   *
   * Can be defined as a regular expression:
   *
   * ```js
   * lib.define('int', /^[0-9]+$/);
   * ```
   *
   * ... or as a function:
   *
   * ```js
   * lib.define('bln', function (obj) {
   *   if ('boolean' === lib.of(obj)) return true;
   *   var blns = [ 'yes', 'no', 'true', 'false', 1, 0 ];
   *   if ('string' === lib.of(obj)) obj = obj.toLowerCase();
   *   return !! ~blns.indexOf(obj);
   * });
   * ```
   *
   * @param {String} type
   * @param {RegExp|Function} test
   * @api public
   */
  
  Library.prototype.define = function(type, test) {
    if (arguments.length === 1) return this.tests[type];
    this.tests[type] = test;
    return this;
  };
  
  /**
   * #### .test (obj, test)
   *
   * Assert that an object is of type. Will first
   * check natives, and if that does not pass it will
   * use the user defined custom tests.
   *
   * ```js
   * assert(lib.test('1', 'int'));
   * assert(lib.test('yes', 'bln'));
   * ```
   *
   * @param {Mixed} object
   * @param {String} type
   * @return {Boolean} result
   * @api public
   */
  
  Library.prototype.test = function(obj, type) {
    if (type === getType(obj)) return true;
    var test = this.tests[type];
  
    if (test && 'regexp' === getType(test)) {
      return test.test(obj);
    } else if (test && 'function' === getType(test)) {
      return test(obj);
    } else {
      throw new ReferenceError('Type test "' + type + '" not defined or invalid.');
    }
  };
  
  },{}],92:[function(require,module,exports){
  
  /**
   * This is the web browser implementation of `debug()`.
   *
   * Expose `debug()` as the module.
   */
  
  exports = module.exports = require('./debug');
  exports.log = log;
  exports.formatArgs = formatArgs;
  exports.save = save;
  exports.load = load;
  exports.useColors = useColors;
  exports.storage = 'undefined' != typeof chrome
                 && 'undefined' != typeof chrome.storage
                    ? chrome.storage.local
                    : localstorage();
  
  /**
   * Colors.
   */
  
  exports.colors = [
    'lightseagreen',
    'forestgreen',
    'goldenrod',
    'dodgerblue',
    'darkorchid',
    'crimson'
  ];
  
  /**
   * Currently only WebKit-based Web Inspectors, Firefox >= v31,
   * and the Firebug extension (any Firefox version) are known
   * to support "%c" CSS customizations.
   *
   * TODO: add a `localStorage` variable to explicitly enable/disable colors
   */
  
  function useColors() {
    // is webkit? http://stackoverflow.com/a/16459606/376773
    return ('WebkitAppearance' in document.documentElement.style) ||
      // is firebug? http://stackoverflow.com/a/398120/376773
      (window.console && (console.firebug || (console.exception && console.table))) ||
      // is firefox >= v31?
      // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
      (navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31);
  }
  
  /**
   * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
   */
  
  exports.formatters.j = function(v) {
    return JSON.stringify(v);
  };
  
  
  /**
   * Colorize log arguments if enabled.
   *
   * @api public
   */
  
  function formatArgs() {
    var args = arguments;
    var useColors = this.useColors;
  
    args[0] = (useColors ? '%c' : '')
      + this.namespace
      + (useColors ? ' %c' : ' ')
      + args[0]
      + (useColors ? '%c ' : ' ')
      + '+' + exports.humanize(this.diff);
  
    if (!useColors) return args;
  
    var c = 'color: ' + this.color;
    args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1));
  
    // the final "%c" is somewhat tricky, because there could be other
    // arguments passed either before or after the %c, so we need to
    // figure out the correct index to insert the CSS into
    var index = 0;
    var lastC = 0;
    args[0].replace(/%[a-z%]/g, function(match) {
      if ('%%' === match) return;
      index++;
      if ('%c' === match) {
        // we only are interested in the *last* %c
        // (the user may have provided their own)
        lastC = index;
      }
    });
  
    args.splice(lastC, 0, c);
    return args;
  }
  
  /**
   * Invokes `console.log()` when available.
   * No-op when `console.log` is not a "function".
   *
   * @api public
   */
  
  function log() {
    // this hackery is required for IE8/9, where
    // the `console.log` function doesn't have 'apply'
    return 'object' === typeof console
      && console.log
      && Function.prototype.apply.call(console.log, console, arguments);
  }
  
  /**
   * Save `namespaces`.
   *
   * @param {String} namespaces
   * @api private
   */
  
  function save(namespaces) {
    try {
      if (null == namespaces) {
        exports.storage.removeItem('debug');
      } else {
        exports.storage.debug = namespaces;
      }
    } catch(e) {}
  }
  
  /**
   * Load `namespaces`.
   *
   * @return {String} returns the previously persisted debug modes
   * @api private
   */
  
  function load() {
    var r;
    try {
      r = exports.storage.debug;
    } catch(e) {}
    return r;
  }
  
  /**
   * Enable namespaces listed in `localStorage.debug` initially.
   */
  
  exports.enable(load());
  
  /**
   * Localstorage attempts to return the localstorage.
   *
   * This is necessary because safari throws
   * when a user disables cookies/localstorage
   * and you attempt to access it.
   *
   * @return {LocalStorage}
   * @api private
   */
  
  function localstorage(){
    try {
      return window.localStorage;
    } catch (e) {}
  }
  
  },{"./debug":93}],93:[function(require,module,exports){
  
  /**
   * This is the common logic for both the Node.js and web browser
   * implementations of `debug()`.
   *
   * Expose `debug()` as the module.
   */
  
  exports = module.exports = debug;
  exports.coerce = coerce;
  exports.disable = disable;
  exports.enable = enable;
  exports.enabled = enabled;
  exports.humanize = require('ms');
  
  /**
   * The currently active debug mode names, and names to skip.
   */
  
  exports.names = [];
  exports.skips = [];
  
  /**
   * Map of special "%n" handling functions, for the debug "format" argument.
   *
   * Valid key names are a single, lowercased letter, i.e. "n".
   */
  
  exports.formatters = {};
  
  /**
   * Previously assigned color.
   */
  
  var prevColor = 0;
  
  /**
   * Previous log timestamp.
   */
  
  var prevTime;
  
  /**
   * Select a color.
   *
   * @return {Number}
   * @api private
   */
  
  function selectColor() {
    return exports.colors[prevColor++ % exports.colors.length];
  }
  
  /**
   * Create a debugger with the given `namespace`.
   *
   * @param {String} namespace
   * @return {Function}
   * @api public
   */
  
  function debug(namespace) {
  
    // define the `disabled` version
    function disabled() {
    }
    disabled.enabled = false;
  
    // define the `enabled` version
    function enabled() {
  
      var self = enabled;
  
      // set `diff` timestamp
      var curr = +new Date();
      var ms = curr - (prevTime || curr);
      self.diff = ms;
      self.prev = prevTime;
      self.curr = curr;
      prevTime = curr;
  
      // add the `color` if not set
      if (null == self.useColors) self.useColors = exports.useColors();
      if (null == self.color && self.useColors) self.color = selectColor();
  
      var args = Array.prototype.slice.call(arguments);
  
      args[0] = exports.coerce(args[0]);
  
      if ('string' !== typeof args[0]) {
        // anything else let's inspect with %o
        args = ['%o'].concat(args);
      }
  
      // apply any `formatters` transformations
      var index = 0;
      args[0] = args[0].replace(/%([a-z%])/g, function(match, format) {
        // if we encounter an escaped % then don't increase the array index
        if (match === '%%') return match;
        index++;
        var formatter = exports.formatters[format];
        if ('function' === typeof formatter) {
          var val = args[index];
          match = formatter.call(self, val);
  
          // now we need to remove `args[index]` since it's inlined in the `format`
          args.splice(index, 1);
          index--;
        }
        return match;
      });
  
      if ('function' === typeof exports.formatArgs) {
        args = exports.formatArgs.apply(self, args);
      }
      var logFn = enabled.log || exports.log || console.log.bind(console);
      logFn.apply(self, args);
    }
    enabled.enabled = true;
  
    var fn = exports.enabled(namespace) ? enabled : disabled;
  
    fn.namespace = namespace;
  
    return fn;
  }
  
  /**
   * Enables a debug mode by namespaces. This can include modes
   * separated by a colon and wildcards.
   *
   * @param {String} namespaces
   * @api public
   */
  
  function enable(namespaces) {
    exports.save(namespaces);
  
    var split = (namespaces || '').split(/[\s,]+/);
    var len = split.length;
  
    for (var i = 0; i < len; i++) {
      if (!split[i]) continue; // ignore empty strings
      namespaces = split[i].replace(/\*/g, '.*?');
      if (namespaces[0] === '-') {
        exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
      } else {
        exports.names.push(new RegExp('^' + namespaces + '$'));
      }
    }
  }
  
  /**
   * Disable debug output.
   *
   * @api public
   */
  
  function disable() {
    exports.enable('');
  }
  
  /**
   * Returns true if the given mode name is enabled, false otherwise.
   *
   * @param {String} name
   * @return {Boolean}
   * @api public
   */
  
  function enabled(name) {
    var i, len;
    for (i = 0, len = exports.skips.length; i < len; i++) {
      if (exports.skips[i].test(name)) {
        return false;
      }
    }
    for (i = 0, len = exports.names.length; i < len; i++) {
      if (exports.names[i].test(name)) {
        return true;
      }
    }
    return false;
  }
  
  /**
   * Coerce `val`.
   *
   * @param {Mixed} val
   * @return {Mixed}
   * @api private
   */
  
  function coerce(val) {
    if (val instanceof Error) return val.stack || val.message;
    return val;
  }
  
  },{"ms":94}],94:[function(require,module,exports){
  /**
   * Helpers.
   */
  
  var s = 1000;
  var m = s * 60;
  var h = m * 60;
  var d = h * 24;
  var y = d * 365.25;
  
  /**
   * Parse or format the given `val`.
   *
   * Options:
   *
   *  - `long` verbose formatting [false]
   *
   * @param {String|Number} val
   * @param {Object} options
   * @return {String|Number}
   * @api public
   */
  
  module.exports = function(val, options){
    options = options || {};
    if ('string' == typeof val) return parse(val);
    return options.long
      ? long(val)
      : short(val);
  };
  
  /**
   * Parse the given `str` and return milliseconds.
   *
   * @param {String} str
   * @return {Number}
   * @api private
   */
  
  function parse(str) {
    str = '' + str;
    if (str.length > 10000) return;
    var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(str);
    if (!match) return;
    var n = parseFloat(match[1]);
    var type = (match[2] || 'ms').toLowerCase();
    switch (type) {
      case 'years':
      case 'year':
      case 'yrs':
      case 'yr':
      case 'y':
        return n * y;
      case 'days':
      case 'day':
      case 'd':
        return n * d;
      case 'hours':
      case 'hour':
      case 'hrs':
      case 'hr':
      case 'h':
        return n * h;
      case 'minutes':
      case 'minute':
      case 'mins':
      case 'min':
      case 'm':
        return n * m;
      case 'seconds':
      case 'second':
      case 'secs':
      case 'sec':
      case 's':
        return n * s;
      case 'milliseconds':
      case 'millisecond':
      case 'msecs':
      case 'msec':
      case 'ms':
        return n;
    }
  }
  
  /**
   * Short format for `ms`.
   *
   * @param {Number} ms
   * @return {String}
   * @api private
   */
  
  function short(ms) {
    if (ms >= d) return Math.round(ms / d) + 'd';
    if (ms >= h) return Math.round(ms / h) + 'h';
    if (ms >= m) return Math.round(ms / m) + 'm';
    if (ms >= s) return Math.round(ms / s) + 's';
    return ms + 'ms';
  }
  
  /**
   * Long format for `ms`.
   *
   * @param {Number} ms
   * @return {String}
   * @api private
   */
  
  function long(ms) {
    return plural(ms, d, 'day')
      || plural(ms, h, 'hour')
      || plural(ms, m, 'minute')
      || plural(ms, s, 'second')
      || ms + ' ms';
  }
  
  /**
   * Pluralization helper.
   */
  
  function plural(ms, n, name) {
    if (ms < n) return;
    if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;
    return Math.ceil(ms / n) + ' ' + name + 's';
  }
  
  },{}],95:[function(require,module,exports){
  var pSlice = Array.prototype.slice;
  var objectKeys = require('./lib/keys.js');
  var isArguments = require('./lib/is_arguments.js');
  
  var deepEqual = module.exports = function (actual, expected, opts) {
    if (!opts) opts = {};
    // 7.1. All identical values are equivalent, as determined by ===.
    if (actual === expected) {
      return true;
  
    } else if (actual instanceof Date && expected instanceof Date) {
      return actual.getTime() === expected.getTime();
  
    // 7.3. Other pairs that do not both pass typeof value == 'object',
    // equivalence is determined by ==.
    } else if (!actual || !expected || typeof actual != 'object' && typeof expected != 'object') {
      return opts.strict ? actual === expected : actual == expected;
  
    // 7.4. For all other Object pairs, including Array objects, equivalence is
    // determined by having the same number of owned properties (as verified
    // with Object.prototype.hasOwnProperty.call), the same set of keys
    // (although not necessarily the same order), equivalent values for every
    // corresponding key, and an identical 'prototype' property. Note: this
    // accounts for both named and indexed properties on Arrays.
    } else {
      return objEquiv(actual, expected, opts);
    }
  }
  
  function isUndefinedOrNull(value) {
    return value === null || value === undefined;
  }
  
  function isBuffer (x) {
    if (!x || typeof x !== 'object' || typeof x.length !== 'number') return false;
    if (typeof x.copy !== 'function' || typeof x.slice !== 'function') {
      return false;
    }
    if (x.length > 0 && typeof x[0] !== 'number') return false;
    return true;
  }
  
  function objEquiv(a, b, opts) {
    var i, key;
    if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
      return false;
    // an identical 'prototype' property.
    if (a.prototype !== b.prototype) return false;
    //~~~I've managed to break Object.keys through screwy arguments passing.
    //   Converting to array solves the problem.
    if (isArguments(a)) {
      if (!isArguments(b)) {
        return false;
      }
      a = pSlice.call(a);
      b = pSlice.call(b);
      return deepEqual(a, b, opts);
    }
    if (isBuffer(a)) {
      if (!isBuffer(b)) {
        return false;
      }
      if (a.length !== b.length) return false;
      for (i = 0; i < a.length; i++) {
        if (a[i] !== b[i]) return false;
      }
      return true;
    }
    try {
      var ka = objectKeys(a),
          kb = objectKeys(b);
    } catch (e) {//happens when one is a string literal and the other isn't
      return false;
    }
    // having the same number of owned properties (keys incorporates
    // hasOwnProperty)
    if (ka.length != kb.length)
      return false;
    //the same set of keys (although not necessarily the same order),
    ka.sort();
    kb.sort();
    //~~~cheap key test
    for (i = ka.length - 1; i >= 0; i--) {
      if (ka[i] != kb[i])
        return false;
    }
    //equivalent values for every corresponding key, and
    //~~~possibly expensive deep test
    for (i = ka.length - 1; i >= 0; i--) {
      key = ka[i];
      if (!deepEqual(a[key], b[key], opts)) return false;
    }
    return typeof a === typeof b;
  }
  
  },{"./lib/is_arguments.js":96,"./lib/keys.js":97}],96:[function(require,module,exports){
  var supportsArgumentsClass = (function(){
    return Object.prototype.toString.call(arguments)
  })() == '[object Arguments]';
  
  exports = module.exports = supportsArgumentsClass ? supported : unsupported;
  
  exports.supported = supported;
  function supported(object) {
    return Object.prototype.toString.call(object) == '[object Arguments]';
  };
  
  exports.unsupported = unsupported;
  function unsupported(object){
    return object &&
      typeof object == 'object' &&
      typeof object.length == 'number' &&
      Object.prototype.hasOwnProperty.call(object, 'callee') &&
      !Object.prototype.propertyIsEnumerable.call(object, 'callee') ||
      false;
  };
  
  },{}],97:[function(require,module,exports){
  exports = module.exports = typeof Object.keys === 'function'
    ? Object.keys : shim;
  
  exports.shim = shim;
  function shim (obj) {
    var keys = [];
    for (var key in obj) keys.push(key);
    return keys;
  }
  
  },{}],98:[function(require,module,exports){
  exports = module.exports = stringify
  exports.getSerialize = serializer
  
  function stringify(obj, replacer, spaces, cycleReplacer) {
    return JSON.stringify(obj, serializer(replacer, cycleReplacer), spaces)
  }
  
  function serializer(replacer, cycleReplacer) {
    var stack = [], keys = []
  
    if (cycleReplacer == null) cycleReplacer = function(key, value) {
      if (stack[0] === value) return "[Circular ~]"
      return "[Circular ~." + keys.slice(0, stack.indexOf(value)).join(".") + "]"
    }
  
    return function(key, value) {
      if (stack.length > 0) {
        var thisPos = stack.indexOf(this)
        ~thisPos ? stack.splice(thisPos + 1) : stack.push(this)
        ~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key)
        if (~stack.indexOf(value)) value = cycleReplacer.call(this, key, value)
      }
      else stack.push(value)
  
      return replacer == null ? value : replacer.call(this, key, value)
    }
  }
  
  },{}],99:[function(require,module,exports){
  (function (global){
  /**
   * @license
   * Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
   * Build: `lodash modern -o ./dist/lodash.js`
   * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
   * Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
   * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   * Available under MIT license <http://lodash.com/license>
   */
  ;(function() {
  
    /** Used as a safe reference for `undefined` in pre ES5 environments */
    var undefined;
  
    /** Used to pool arrays and objects used internally */
    var arrayPool = [],
        objectPool = [];
  
    /** Used to generate unique IDs */
    var idCounter = 0;
  
    /** Used to prefix keys to avoid issues with `__proto__` and properties on `Object.prototype` */
    var keyPrefix = +new Date + '';
  
    /** Used as the size when optimizations are enabled for large arrays */
    var largeArraySize = 75;
  
    /** Used as the max size of the `arrayPool` and `objectPool` */
    var maxPoolSize = 40;
  
    /** Used to detect and test whitespace */
    var whitespace = (
      // whitespace
      ' \t\x0B\f\xA0\ufeff' +
  
      // line terminators
      '\n\r\u2028\u2029' +
  
      // unicode category "Zs" space separators
      '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000'
    );
  
    /** Used to match empty string literals in compiled template source */
    var reEmptyStringLeading = /\b__p \+= '';/g,
        reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
        reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
  
    /**
     * Used to match ES6 template delimiters
     * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-literals-string-literals
     */
    var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
  
    /** Used to match regexp flags from their coerced string values */
    var reFlags = /\w*$/;
  
    /** Used to detected named functions */
    var reFuncName = /^\s*function[ \n\r\t]+\w/;
  
    /** Used to match "interpolate" template delimiters */
    var reInterpolate = /<%=([\s\S]+?)%>/g;
  
    /** Used to match leading whitespace and zeros to be removed */
    var reLeadingSpacesAndZeros = RegExp('^[' + whitespace + ']*0+(?=.$)');
  
    /** Used to ensure capturing order of template delimiters */
    var reNoMatch = /($^)/;
  
    /** Used to detect functions containing a `this` reference */
    var reThis = /\bthis\b/;
  
    /** Used to match unescaped characters in compiled string literals */
    var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
  
    /** Used to assign default `context` object properties */
    var contextProps = [
      'Array', 'Boolean', 'Date', 'Function', 'Math', 'Number', 'Object',
      'RegExp', 'String', '_', 'attachEvent', 'clearTimeout', 'isFinite', 'isNaN',
      'parseInt', 'setTimeout'
    ];
  
    /** Used to make template sourceURLs easier to identify */
    var templateCounter = 0;
  
    /** `Object#toString` result shortcuts */
    var argsClass = '[object Arguments]',
        arrayClass = '[object Array]',
        boolClass = '[object Boolean]',
        dateClass = '[object Date]',
        funcClass = '[object Function]',
        numberClass = '[object Number]',
        objectClass = '[object Object]',
        regexpClass = '[object RegExp]',
        stringClass = '[object String]';
  
    /** Used to identify object classifications that `_.clone` supports */
    var cloneableClasses = {};
    cloneableClasses[funcClass] = false;
    cloneableClasses[argsClass] = cloneableClasses[arrayClass] =
    cloneableClasses[boolClass] = cloneableClasses[dateClass] =
    cloneableClasses[numberClass] = cloneableClasses[objectClass] =
    cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true;
  
    /** Used as an internal `_.debounce` options object */
    var debounceOptions = {
      'leading': false,
      'maxWait': 0,
      'trailing': false
    };
  
    /** Used as the property descriptor for `__bindData__` */
    var descriptor = {
      'configurable': false,
      'enumerable': false,
      'value': null,
      'writable': false
    };
  
    /** Used to determine if values are of the language type Object */
    var objectTypes = {
      'boolean': false,
      'function': true,
      'object': true,
      'number': false,
      'string': false,
      'undefined': false
    };
  
    /** Used to escape characters for inclusion in compiled string literals */
    var stringEscapes = {
      '\\': '\\',
      "'": "'",
      '\n': 'n',
      '\r': 'r',
      '\t': 't',
      '\u2028': 'u2028',
      '\u2029': 'u2029'
    };
  
    /** Used as a reference to the global object */
    var root = (objectTypes[typeof window] && window) || this;
  
    /** Detect free variable `exports` */
    var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
  
    /** Detect free variable `module` */
    var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
  
    /** Detect the popular CommonJS extension `module.exports` */
    var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;
  
    /** Detect free variable `global` from Node.js or Browserified code and use it as `root` */
    var freeGlobal = objectTypes[typeof global] && global;
    if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal)) {
      root = freeGlobal;
    }
  
    /*--------------------------------------------------------------------------*/
  
    /**
     * The base implementation of `_.indexOf` without support for binary searches
     * or `fromIndex` constraints.
     *
     * @private
     * @param {Array} array The array to search.
     * @param {*} value The value to search for.
     * @param {number} [fromIndex=0] The index to search from.
     * @returns {number} Returns the index of the matched value or `-1`.
     */
    function baseIndexOf(array, value, fromIndex) {
      var index = (fromIndex || 0) - 1,
          length = array ? array.length : 0;
  
      while (++index < length) {
        if (array[index] === value) {
          return index;
        }
      }
      return -1;
    }
  
    /**
     * An implementation of `_.contains` for cache objects that mimics the return
     * signature of `_.indexOf` by returning `0` if the value is found, else `-1`.
     *
     * @private
     * @param {Object} cache The cache object to inspect.
     * @param {*} value The value to search for.
     * @returns {number} Returns `0` if `value` is found, else `-1`.
     */
    function cacheIndexOf(cache, value) {
      var type = typeof value;
      cache = cache.cache;
  
      if (type == 'boolean' || value == null) {
        return cache[value] ? 0 : -1;
      }
      if (type != 'number' && type != 'string') {
        type = 'object';
      }
      var key = type == 'number' ? value : keyPrefix + value;
      cache = (cache = cache[type]) && cache[key];
  
      return type == 'object'
        ? (cache && baseIndexOf(cache, value) > -1 ? 0 : -1)
        : (cache ? 0 : -1);
    }
  
    /**
     * Adds a given value to the corresponding cache object.
     *
     * @private
     * @param {*} value The value to add to the cache.
     */
    function cachePush(value) {
      var cache = this.cache,
          type = typeof value;
  
      if (type == 'boolean' || value == null) {
        cache[value] = true;
      } else {
        if (type != 'number' && type != 'string') {
          type = 'object';
        }
        var key = type == 'number' ? value : keyPrefix + value,
            typeCache = cache[type] || (cache[type] = {});
  
        if (type == 'object') {
          (typeCache[key] || (typeCache[key] = [])).push(value);
        } else {
          typeCache[key] = true;
        }
      }
    }
  
    /**
     * Used by `_.max` and `_.min` as the default callback when a given
     * collection is a string value.
     *
     * @private
     * @param {string} value The character to inspect.
     * @returns {number} Returns the code unit of given character.
     */
    function charAtCallback(value) {
      return value.charCodeAt(0);
    }
  
    /**
     * Used by `sortBy` to compare transformed `collection` elements, stable sorting
     * them in ascending order.
     *
     * @private
     * @param {Object} a The object to compare to `b`.
     * @param {Object} b The object to compare to `a`.
     * @returns {number} Returns the sort order indicator of `1` or `-1`.
     */
    function compareAscending(a, b) {
      var ac = a.criteria,
          bc = b.criteria,
          index = -1,
          length = ac.length;
  
      while (++index < length) {
        var value = ac[index],
            other = bc[index];
  
        if (value !== other) {
          if (value > other || typeof value == 'undefined') {
            return 1;
          }
          if (value < other || typeof other == 'undefined') {
            return -1;
          }
        }
      }
      // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
      // that causes it, under certain circumstances, to return the same value for
      // `a` and `b`. See https://github.com/jashkenas/underscore/pull/1247
      //
      // This also ensures a stable sort in V8 and other engines.
      // See http://code.google.com/p/v8/issues/detail?id=90
      return a.index - b.index;
    }
  
    /**
     * Creates a cache object to optimize linear searches of large arrays.
     *
     * @private
     * @param {Array} [array=[]] The array to search.
     * @returns {null|Object} Returns the cache object or `null` if caching should not be used.
     */
    function createCache(array) {
      var index = -1,
          length = array.length,
          first = array[0],
          mid = array[(length / 2) | 0],
          last = array[length - 1];
  
      if (first && typeof first == 'object' &&
          mid && typeof mid == 'object' && last && typeof last == 'object') {
        return false;
      }
      var cache = getObject();
      cache['false'] = cache['null'] = cache['true'] = cache['undefined'] = false;
  
      var result = getObject();
      result.array = array;
      result.cache = cache;
      result.push = cachePush;
  
      while (++index < length) {
        result.push(array[index]);
      }
      return result;
    }
  
    /**
     * Used by `template` to escape characters for inclusion in compiled
     * string literals.
     *
     * @private
     * @param {string} match The matched character to escape.
     * @returns {string} Returns the escaped character.
     */
    function escapeStringChar(match) {
      return '\\' + stringEscapes[match];
    }
  
    /**
     * Gets an array from the array pool or creates a new one if the pool is empty.
     *
     * @private
     * @returns {Array} The array from the pool.
     */
    function getArray() {
      return arrayPool.pop() || [];
    }
  
    /**
     * Gets an object from the object pool or creates a new one if the pool is empty.
     *
     * @private
     * @returns {Object} The object from the pool.
     */
    function getObject() {
      return objectPool.pop() || {
        'array': null,
        'cache': null,
        'criteria': null,
        'false': false,
        'index': 0,
        'null': false,
        'number': null,
        'object': null,
        'push': null,
        'string': null,
        'true': false,
        'undefined': false,
        'value': null
      };
    }
  
    /**
     * Releases the given array back to the array pool.
     *
     * @private
     * @param {Array} [array] The array to release.
     */
    function releaseArray(array) {
      array.length = 0;
      if (arrayPool.length < maxPoolSize) {
        arrayPool.push(array);
      }
    }
  
    /**
     * Releases the given object back to the object pool.
     *
     * @private
     * @param {Object} [object] The object to release.
     */
    function releaseObject(object) {
      var cache = object.cache;
      if (cache) {
        releaseObject(cache);
      }
      object.array = object.cache = object.criteria = object.object = object.number = object.string = object.value = null;
      if (objectPool.length < maxPoolSize) {
        objectPool.push(object);
      }
    }
  
    /**
     * Slices the `collection` from the `start` index up to, but not including,
     * the `end` index.
     *
     * Note: This function is used instead of `Array#slice` to support node lists
     * in IE < 9 and to ensure dense arrays are returned.
     *
     * @private
     * @param {Array|Object|string} collection The collection to slice.
     * @param {number} start The start index.
     * @param {number} end The end index.
     * @returns {Array} Returns the new array.
     */
    function slice(array, start, end) {
      start || (start = 0);
      if (typeof end == 'undefined') {
        end = array ? array.length : 0;
      }
      var index = -1,
          length = end - start || 0,
          result = Array(length < 0 ? 0 : length);
  
      while (++index < length) {
        result[index] = array[start + index];
      }
      return result;
    }
  
    /*--------------------------------------------------------------------------*/
  
    /**
     * Create a new `lodash` function using the given context object.
     *
     * @static
     * @memberOf _
     * @category Utilities
     * @param {Object} [context=root] The context object.
     * @returns {Function} Returns the `lodash` function.
     */
    function runInContext(context) {
      // Avoid issues with some ES3 environments that attempt to use values, named
      // after built-in constructors like `Object`, for the creation of literals.
      // ES5 clears this up by stating that literals must use built-in constructors.
      // See http://es5.github.io/#x11.1.5.
      context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root;
  
      /** Native constructor references */
      var Array = context.Array,
          Boolean = context.Boolean,
          Date = context.Date,
          Function = context.Function,
          Math = context.Math,
          Number = context.Number,
          Object = context.Object,
          RegExp = context.RegExp,
          String = context.String,
          TypeError = context.TypeError;
  
      /**
       * Used for `Array` method references.
       *
       * Normally `Array.prototype` would suffice, however, using an array literal
       * avoids issues in Narwhal.
       */
      var arrayRef = [];
  
      /** Used for native method references */
      var objectProto = Object.prototype;
  
      /** Used to restore the original `_` reference in `noConflict` */
      var oldDash = context._;
  
      /** Used to resolve the internal [[Class]] of values */
      var toString = objectProto.toString;
  
      /** Used to detect if a method is native */
      var reNative = RegExp('^' +
        String(toString)
          .replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
          .replace(/toString| for [^\]]+/g, '.*?') + '$'
      );
  
      /** Native method shortcuts */
      var ceil = Math.ceil,
          clearTimeout = context.clearTimeout,
          floor = Math.floor,
          fnToString = Function.prototype.toString,
          getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
          hasOwnProperty = objectProto.hasOwnProperty,
          push = arrayRef.push,
          setTimeout = context.setTimeout,
          splice = arrayRef.splice,
          unshift = arrayRef.unshift;
  
      /** Used to set meta data on functions */
      var defineProperty = (function() {
        // IE 8 only accepts DOM elements
        try {
          var o = {},
              func = isNative(func = Object.defineProperty) && func,
              result = func(o, o, o) && func;
        } catch(e) { }
        return result;
      }());
  
      /* Native method shortcuts for methods with the same name as other `lodash` methods */
      var nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate,
          nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray,
          nativeIsFinite = context.isFinite,
          nativeIsNaN = context.isNaN,
          nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys,
          nativeMax = Math.max,
          nativeMin = Math.min,
          nativeParseInt = context.parseInt,
          nativeRandom = Math.random;
  
      /** Used to lookup a built-in constructor by [[Class]] */
      var ctorByClass = {};
      ctorByClass[arrayClass] = Array;
      ctorByClass[boolClass] = Boolean;
      ctorByClass[dateClass] = Date;
      ctorByClass[funcClass] = Function;
      ctorByClass[objectClass] = Object;
      ctorByClass[numberClass] = Number;
      ctorByClass[regexpClass] = RegExp;
      ctorByClass[stringClass] = String;
  
      /*--------------------------------------------------------------------------*/
  
      /**
       * Creates a `lodash` object which wraps the given value to enable intuitive
       * method chaining.
       *
       * In addition to Lo-Dash methods, wrappers also have the following `Array` methods:
       * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`,
       * and `unshift`
       *
       * Chaining is supported in custom builds as long as the `value` method is
       * implicitly or explicitly included in the build.
       *
       * The chainable wrapper functions are:
       * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`,
       * `compose`, `concat`, `countBy`, `create`, `createCallback`, `curry`,
       * `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, `flatten`,
       * `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`,
       * `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`,
       * `invoke`, `keys`, `map`, `max`, `memoize`, `merge`, `min`, `object`, `omit`,
       * `once`, `pairs`, `partial`, `partialRight`, `pick`, `pluck`, `pull`, `push`,
       * `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`,
       * `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`,
       * `union`, `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`,
       * and `zip`
       *
       * The non-chainable wrapper functions are:
       * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `findIndex`,
       * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `has`, `identity`,
       * `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`,
       * `isEmpty`, `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`,
       * `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`,
       * `lastIndexOf`, `mixin`, `noConflict`, `parseInt`, `pop`, `random`, `reduce`,
       * `reduceRight`, `result`, `shift`, `size`, `some`, `sortedIndex`, `runInContext`,
       * `template`, `unescape`, `uniqueId`, and `value`
       *
       * The wrapper functions `first` and `last` return wrapped values when `n` is
       * provided, otherwise they return unwrapped values.
       *
       * Explicit chaining can be enabled by using the `_.chain` method.
       *
       * @name _
       * @constructor
       * @category Chaining
       * @param {*} value The value to wrap in a `lodash` instance.
       * @returns {Object} Returns a `lodash` instance.
       * @example
       *
       * var wrapped = _([1, 2, 3]);
       *
       * // returns an unwrapped value
       * wrapped.reduce(function(sum, num) {
       *   return sum + num;
       * });
       * // => 6
       *
       * // returns a wrapped value
       * var squares = wrapped.map(function(num) {
       *   return num * num;
       * });
       *
       * _.isArray(squares);
       * // => false
       *
       * _.isArray(squares.value());
       * // => true
       */
      function lodash(value) {
        // don't wrap if already wrapped, even if wrapped by a different `lodash` constructor
        return (value && typeof value == 'object' && !isArray(value) && hasOwnProperty.call(value, '__wrapped__'))
         ? value
         : new lodashWrapper(value);
      }
  
      /**
       * A fast path for creating `lodash` wrapper objects.
       *
       * @private
       * @param {*} value The value to wrap in a `lodash` instance.
       * @param {boolean} chainAll A flag to enable chaining for all methods
       * @returns {Object} Returns a `lodash` instance.
       */
      function lodashWrapper(value, chainAll) {
        this.__chain__ = !!chainAll;
        this.__wrapped__ = value;
      }
      // ensure `new lodashWrapper` is an instance of `lodash`
      lodashWrapper.prototype = lodash.prototype;
  
      /**
       * An object used to flag environments features.
       *
       * @static
       * @memberOf _
       * @type Object
       */
      var support = lodash.support = {};
  
      /**
       * Detect if functions can be decompiled by `Function#toString`
       * (all but PS3 and older Opera mobile browsers & avoided in Windows 8 apps).
       *
       * @memberOf _.support
       * @type boolean
       */
      support.funcDecomp = !isNative(context.WinRTError) && reThis.test(runInContext);
  
      /**
       * Detect if `Function#name` is supported (all but IE).
       *
       * @memberOf _.support
       * @type boolean
       */
      support.funcNames = typeof Function.name == 'string';
  
      /**
       * By default, the template delimiters used by Lo-Dash are similar to those in
       * embedded Ruby (ERB). Change the following template settings to use alternative
       * delimiters.
       *
       * @static
       * @memberOf _
       * @type Object
       */
      lodash.templateSettings = {
  
        /**
         * Used to detect `data` property values to be HTML-escaped.
         *
         * @memberOf _.templateSettings
         * @type RegExp
         */
        'escape': /<%-([\s\S]+?)%>/g,
  
        /**
         * Used to detect code to be evaluated.
         *
         * @memberOf _.templateSettings
         * @type RegExp
         */
        'evaluate': /<%([\s\S]+?)%>/g,
  
        /**
         * Used to detect `data` property values to inject.
         *
         * @memberOf _.templateSettings
         * @type RegExp
         */
        'interpolate': reInterpolate,
  
        /**
         * Used to reference the data object in the template text.
         *
         * @memberOf _.templateSettings
         * @type string
         */
        'variable': '',
  
        /**
         * Used to import variables into the compiled template.
         *
         * @memberOf _.templateSettings
         * @type Object
         */
        'imports': {
  
          /**
           * A reference to the `lodash` function.
           *
           * @memberOf _.templateSettings.imports
           * @type Function
           */
          '_': lodash
        }
      };
  
      /*--------------------------------------------------------------------------*/
  
      /**
       * The base implementation of `_.bind` that creates the bound function and
       * sets its meta data.
       *
       * @private
       * @param {Array} bindData The bind data array.
       * @returns {Function} Returns the new bound function.
       */
      function baseBind(bindData) {
        var func = bindData[0],
            partialArgs = bindData[2],
            thisArg = bindData[4];
  
        function bound() {
          // `Function#bind` spec
          // http://es5.github.io/#x15.3.4.5
          if (partialArgs) {
            // avoid `arguments` object deoptimizations by using `slice` instead
            // of `Array.prototype.slice.call` and not assigning `arguments` to a
            // variable as a ternary expression
            var args = slice(partialArgs);
            push.apply(args, arguments);
          }
          // mimic the constructor's `return` behavior
          // http://es5.github.io/#x13.2.2
          if (this instanceof bound) {
            // ensure `new bound` is an instance of `func`
            var thisBinding = baseCreate(func.prototype),
                result = func.apply(thisBinding, args || arguments);
            return isObject(result) ? result : thisBinding;
          }
          return func.apply(thisArg, args || arguments);
        }
        setBindData(bound, bindData);
        return bound;
      }
  
      /**
       * The base implementation of `_.clone` without argument juggling or support
       * for `thisArg` binding.
       *
       * @private
       * @param {*} value The value to clone.
       * @param {boolean} [isDeep=false] Specify a deep clone.
       * @param {Function} [callback] The function to customize cloning values.
       * @param {Array} [stackA=[]] Tracks traversed source objects.
       * @param {Array} [stackB=[]] Associates clones with source counterparts.
       * @returns {*} Returns the cloned value.
       */
      function baseClone(value, isDeep, callback, stackA, stackB) {
        if (callback) {
          var result = callback(value);
          if (typeof result != 'undefined') {
            return result;
          }
        }
        // inspect [[Class]]
        var isObj = isObject(value);
        if (isObj) {
          var className = toString.call(value);
          if (!cloneableClasses[className]) {
            return value;
          }
          var ctor = ctorByClass[className];
          switch (className) {
            case boolClass:
            case dateClass:
              return new ctor(+value);
  
            case numberClass:
            case stringClass:
              return new ctor(value);
  
            case regexpClass:
              result = ctor(value.source, reFlags.exec(value));
              result.lastIndex = value.lastIndex;
              return result;
          }
        } else {
          return value;
        }
        var isArr = isArray(value);
        if (isDeep) {
          // check for circular references and return corresponding clone
          var initedStack = !stackA;
          stackA || (stackA = getArray());
          stackB || (stackB = getArray());
  
          var length = stackA.length;
          while (length--) {
            if (stackA[length] == value) {
              return stackB[length];
            }
          }
          result = isArr ? ctor(value.length) : {};
        }
        else {
          result = isArr ? slice(value) : assign({}, value);
        }
        // add array properties assigned by `RegExp#exec`
        if (isArr) {
          if (hasOwnProperty.call(value, 'index')) {
            result.index = value.index;
          }
          if (hasOwnProperty.call(value, 'input')) {
            result.input = value.input;
          }
        }
        // exit for shallow clone
        if (!isDeep) {
          return result;
        }
        // add the source value to the stack of traversed objects
        // and associate it with its clone
        stackA.push(value);
        stackB.push(result);
  
        // recursively populate clone (susceptible to call stack limits)
        (isArr ? forEach : forOwn)(value, function(objValue, key) {
          result[key] = baseClone(objValue, isDeep, callback, stackA, stackB);
        });
  
        if (initedStack) {
          releaseArray(stackA);
          releaseArray(stackB);
        }
        return result;
      }
  
      /**
       * The base implementation of `_.create` without support for assigning
       * properties to the created object.
       *
       * @private
       * @param {Object} prototype The object to inherit from.
       * @returns {Object} Returns the new object.
       */
      function baseCreate(prototype, properties) {
        return isObject(prototype) ? nativeCreate(prototype) : {};
      }
      // fallback for browsers without `Object.create`
      if (!nativeCreate) {
        baseCreate = (function() {
          function Object() {}
          return function(prototype) {
            if (isObject(prototype)) {
              Object.prototype = prototype;
              var result = new Object;
              Object.prototype = null;
            }
            return result || context.Object();
          };
        }());
      }
  
      /**
       * The base implementation of `_.createCallback` without support for creating
       * "_.pluck" or "_.where" style callbacks.
       *
       * @private
       * @param {*} [func=identity] The value to convert to a callback.
       * @param {*} [thisArg] The `this` binding of the created callback.
       * @param {number} [argCount] The number of arguments the callback accepts.
       * @returns {Function} Returns a callback function.
       */
      function baseCreateCallback(func, thisArg, argCount) {
        if (typeof func != 'function') {
          return identity;
        }
        // exit early for no `thisArg` or already bound by `Function#bind`
        if (typeof thisArg == 'undefined' || !('prototype' in func)) {
          return func;
        }
        var bindData = func.__bindData__;
        if (typeof bindData == 'undefined') {
          if (support.funcNames) {
            bindData = !func.name;
          }
          bindData = bindData || !support.funcDecomp;
          if (!bindData) {
            var source = fnToString.call(func);
            if (!support.funcNames) {
              bindData = !reFuncName.test(source);
            }
            if (!bindData) {
              // checks if `func` references the `this` keyword and stores the result
              bindData = reThis.test(source);
              setBindData(func, bindData);
            }
          }
        }
        // exit early if there are no `this` references or `func` is bound
        if (bindData === false || (bindData !== true && bindData[1] & 1)) {
          return func;
        }
        switch (argCount) {
          case 1: return function(value) {
            return func.call(thisArg, value);
          };
          case 2: return function(a, b) {
            return func.call(thisArg, a, b);
          };
          case 3: return function(value, index, collection) {
            return func.call(thisArg, value, index, collection);
          };
          case 4: return function(accumulator, value, index, collection) {
            return func.call(thisArg, accumulator, value, index, collection);
          };
        }
        return bind(func, thisArg);
      }
  
      /**
       * The base implementation of `createWrapper` that creates the wrapper and
       * sets its meta data.
       *
       * @private
       * @param {Array} bindData The bind data array.
       * @returns {Function} Returns the new function.
       */
      function baseCreateWrapper(bindData) {
        var func = bindData[0],
            bitmask = bindData[1],
            partialArgs = bindData[2],
            partialRightArgs = bindData[3],
            thisArg = bindData[4],
            arity = bindData[5];
  
        var isBind = bitmask & 1,
            isBindKey = bitmask & 2,
            isCurry = bitmask & 4,
            isCurryBound = bitmask & 8,
            key = func;
  
        function bound() {
          var thisBinding = isBind ? thisArg : this;
          if (partialArgs) {
            var args = slice(partialArgs);
            push.apply(args, arguments);
          }
          if (partialRightArgs || isCurry) {
            args || (args = slice(arguments));
            if (partialRightArgs) {
              push.apply(args, partialRightArgs);
            }
            if (isCurry && args.length < arity) {
              bitmask |= 16 & ~32;
              return baseCreateWrapper([func, (isCurryBound ? bitmask : bitmask & ~3), args, null, thisArg, arity]);
            }
          }
          args || (args = arguments);
          if (isBindKey) {
            func = thisBinding[key];
          }
          if (this instanceof bound) {
            thisBinding = baseCreate(func.prototype);
            var result = func.apply(thisBinding, args);
            return isObject(result) ? result : thisBinding;
          }
          return func.apply(thisBinding, args);
        }
        setBindData(bound, bindData);
        return bound;
      }
  
      /**
       * The base implementation of `_.difference` that accepts a single array
       * of values to exclude.
       *
       * @private
       * @param {Array} array The array to process.
       * @param {Array} [values] The array of values to exclude.
       * @returns {Array} Returns a new array of filtered values.
       */
      function baseDifference(array, values) {
        var index = -1,
            indexOf = getIndexOf(),
            length = array ? array.length : 0,
            isLarge = length >= largeArraySize && indexOf === baseIndexOf,
            result = [];
  
        if (isLarge) {
          var cache = createCache(values);
          if (cache) {
            indexOf = cacheIndexOf;
            values = cache;
          } else {
            isLarge = false;
          }
        }
        while (++index < length) {
          var value = array[index];
          if (indexOf(values, value) < 0) {
            result.push(value);
          }
        }
        if (isLarge) {
          releaseObject(values);
        }
        return result;
      }
  
      /**
       * The base implementation of `_.flatten` without support for callback
       * shorthands or `thisArg` binding.
       *
       * @private
       * @param {Array} array The array to flatten.
       * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
       * @param {boolean} [isStrict=false] A flag to restrict flattening to arrays and `arguments` objects.
       * @param {number} [fromIndex=0] The index to start from.
       * @returns {Array} Returns a new flattened array.
       */
      function baseFlatten(array, isShallow, isStrict, fromIndex) {
        var index = (fromIndex || 0) - 1,
            length = array ? array.length : 0,
            result = [];
  
        while (++index < length) {
          var value = array[index];
  
          if (value && typeof value == 'object' && typeof value.length == 'number'
              && (isArray(value) || isArguments(value))) {
            // recursively flatten arrays (susceptible to call stack limits)
            if (!isShallow) {
              value = baseFlatten(value, isShallow, isStrict);
            }
            var valIndex = -1,
                valLength = value.length,
                resIndex = result.length;
  
            result.length += valLength;
            while (++valIndex < valLength) {
              result[resIndex++] = value[valIndex];
            }
          } else if (!isStrict) {
            result.push(value);
          }
        }
        return result;
      }
  
      /**
       * The base implementation of `_.isEqual`, without support for `thisArg` binding,
       * that allows partial "_.where" style comparisons.
       *
       * @private
       * @param {*} a The value to compare.
       * @param {*} b The other value to compare.
       * @param {Function} [callback] The function to customize comparing values.
       * @param {Function} [isWhere=false] A flag to indicate performing partial comparisons.
       * @param {Array} [stackA=[]] Tracks traversed `a` objects.
       * @param {Array} [stackB=[]] Tracks traversed `b` objects.
       * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
       */
      function baseIsEqual(a, b, callback, isWhere, stackA, stackB) {
        // used to indicate that when comparing objects, `a` has at least the properties of `b`
        if (callback) {
          var result = callback(a, b);
          if (typeof result != 'undefined') {
            return !!result;
          }
        }
        // exit early for identical values
        if (a === b) {
          // treat `+0` vs. `-0` as not equal
          return a !== 0 || (1 / a == 1 / b);
        }
        var type = typeof a,
            otherType = typeof b;
  
        // exit early for unlike primitive values
        if (a === a &&
            !(a && objectTypes[type]) &&
            !(b && objectTypes[otherType])) {
          return false;
        }
        // exit early for `null` and `undefined` avoiding ES3's Function#call behavior
        // http://es5.github.io/#x15.3.4.4
        if (a == null || b == null) {
          return a === b;
        }
        // compare [[Class]] names
        var className = toString.call(a),
            otherClass = toString.call(b);
  
        if (className == argsClass) {
          className = objectClass;
        }
        if (otherClass == argsClass) {
          otherClass = objectClass;
        }
        if (className != otherClass) {
          return false;
        }
        switch (className) {
          case boolClass:
          case dateClass:
            // coerce dates and booleans to numbers, dates to milliseconds and booleans
            // to `1` or `0` treating invalid dates coerced to `NaN` as not equal
            return +a == +b;
  
          case numberClass:
            // treat `NaN` vs. `NaN` as equal
            return (a != +a)
              ? b != +b
              // but treat `+0` vs. `-0` as not equal
              : (a == 0 ? (1 / a == 1 / b) : a == +b);
  
          case regexpClass:
          case stringClass:
            // coerce regexes to strings (http://es5.github.io/#x15.10.6.4)
            // treat string primitives and their corresponding object instances as equal
            return a == String(b);
        }
        var isArr = className == arrayClass;
        if (!isArr) {
          // unwrap any `lodash` wrapped values
          var aWrapped = hasOwnProperty.call(a, '__wrapped__'),
              bWrapped = hasOwnProperty.call(b, '__wrapped__');
  
          if (aWrapped || bWrapped) {
            return baseIsEqual(aWrapped ? a.__wrapped__ : a, bWrapped ? b.__wrapped__ : b, callback, isWhere, stackA, stackB);
          }
          // exit for functions and DOM nodes
          if (className != objectClass) {
            return false;
          }
          // in older versions of Opera, `arguments` objects have `Array` constructors
          var ctorA = a.constructor,
              ctorB = b.constructor;
  
          // non `Object` object instances with different constructors are not equal
          if (ctorA != ctorB &&
                !(isFunction(ctorA) && ctorA instanceof ctorA && isFunction(ctorB) && ctorB instanceof ctorB) &&
                ('constructor' in a && 'constructor' in b)
              ) {
            return false;
          }
        }
        // assume cyclic structures are equal
        // the algorithm for detecting cyclic structures is adapted from ES 5.1
        // section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3)
        var initedStack = !stackA;
        stackA || (stackA = getArray());
        stackB || (stackB = getArray());
  
        var length = stackA.length;
        while (length--) {
          if (stackA[length] == a) {
            return stackB[length] == b;
          }
        }
        var size = 0;
        result = true;
  
        // add `a` and `b` to the stack of traversed objects
        stackA.push(a);
        stackB.push(b);
  
        // recursively compare objects and arrays (susceptible to call stack limits)
        if (isArr) {
          // compare lengths to determine if a deep comparison is necessary
          length = a.length;
          size = b.length;
          result = size == length;
  
          if (result || isWhere) {
            // deep compare the contents, ignoring non-numeric properties
            while (size--) {
              var index = length,
                  value = b[size];
  
              if (isWhere) {
                while (index--) {
                  if ((result = baseIsEqual(a[index], value, callback, isWhere, stackA, stackB))) {
                    break;
                  }
                }
              } else if (!(result = baseIsEqual(a[size], value, callback, isWhere, stackA, stackB))) {
                break;
              }
            }
          }
        }
        else {
          // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`
          // which, in this case, is more costly
          forIn(b, function(value, key, b) {
            if (hasOwnProperty.call(b, key)) {
              // count the number of properties.
              size++;
              // deep compare each property value.
              return (result = hasOwnProperty.call(a, key) && baseIsEqual(a[key], value, callback, isWhere, stackA, stackB));
            }
          });
  
          if (result && !isWhere) {
            // ensure both objects have the same number of properties
            forIn(a, function(value, key, a) {
              if (hasOwnProperty.call(a, key)) {
                // `size` will be `-1` if `a` has more properties than `b`
                return (result = --size > -1);
              }
            });
          }
        }
        stackA.pop();
        stackB.pop();
  
        if (initedStack) {
          releaseArray(stackA);
          releaseArray(stackB);
        }
        return result;
      }
  
      /**
       * The base implementation of `_.merge` without argument juggling or support
       * for `thisArg` binding.
       *
       * @private
       * @param {Object} object The destination object.
       * @param {Object} source The source object.
       * @param {Function} [callback] The function to customize merging properties.
       * @param {Array} [stackA=[]] Tracks traversed source objects.
       * @param {Array} [stackB=[]] Associates values with source counterparts.
       */
      function baseMerge(object, source, callback, stackA, stackB) {
        (isArray(source) ? forEach : forOwn)(source, function(source, key) {
          var found,
              isArr,
              result = source,
              value = object[key];
  
          if (source && ((isArr = isArray(source)) || isPlainObject(source))) {
            // avoid merging previously merged cyclic sources
            var stackLength = stackA.length;
            while (stackLength--) {
              if ((found = stackA[stackLength] == source)) {
                value = stackB[stackLength];
                break;
              }
            }
            if (!found) {
              var isShallow;
              if (callback) {
                result = callback(value, source);
                if ((isShallow = typeof result != 'undefined')) {
                  value = result;
                }
              }
              if (!isShallow) {
                value = isArr
                  ? (isArray(value) ? value : [])
                  : (isPlainObject(value) ? value : {});
              }
              // add `source` and associated `value` to the stack of traversed objects
              stackA.push(source);
              stackB.push(value);
  
              // recursively merge objects and arrays (susceptible to call stack limits)
              if (!isShallow) {
                baseMerge(value, source, callback, stackA, stackB);
              }
            }
          }
          else {
            if (callback) {
              result = callback(value, source);
              if (typeof result == 'undefined') {
                result = source;
              }
            }
            if (typeof result != 'undefined') {
              value = result;
            }
          }
          object[key] = value;
        });
      }
  
      /**
       * The base implementation of `_.random` without argument juggling or support
       * for returning floating-point numbers.
       *
       * @private
       * @param {number} min The minimum possible value.
       * @param {number} max The maximum possible value.
       * @returns {number} Returns a random number.
       */
      function baseRandom(min, max) {
        return min + floor(nativeRandom() * (max - min + 1));
      }
  
      /**
       * The base implementation of `_.uniq` without support for callback shorthands
       * or `thisArg` binding.
       *
       * @private
       * @param {Array} array The array to process.
       * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
       * @param {Function} [callback] The function called per iteration.
       * @returns {Array} Returns a duplicate-value-free array.
       */
      function baseUniq(array, isSorted, callback) {
        var index = -1,
            indexOf = getIndexOf(),
            length = array ? array.length : 0,
            result = [];
  
        var isLarge = !isSorted && length >= largeArraySize && indexOf === baseIndexOf,
            seen = (callback || isLarge) ? getArray() : result;
  
        if (isLarge) {
          var cache = createCache(seen);
          indexOf = cacheIndexOf;
          seen = cache;
        }
        while (++index < length) {
          var value = array[index],
              computed = callback ? callback(value, index, array) : value;
  
          if (isSorted
                ? !index || seen[seen.length - 1] !== computed
                : indexOf(seen, computed) < 0
              ) {
            if (callback || isLarge) {
              seen.push(computed);
            }
            result.push(value);
          }
        }
        if (isLarge) {
          releaseArray(seen.array);
          releaseObject(seen);
        } else if (callback) {
          releaseArray(seen);
        }
        return result;
      }
  
      /**
       * Creates a function that aggregates a collection, creating an object composed
       * of keys generated from the results of running each element of the collection
       * through a callback. The given `setter` function sets the keys and values
       * of the composed object.
       *
       * @private
       * @param {Function} setter The setter function.
       * @returns {Function} Returns the new aggregator function.
       */
      function createAggregator(setter) {
        return function(collection, callback, thisArg) {
          var result = {};
          callback = lodash.createCallback(callback, thisArg, 3);
  
          var index = -1,
              length = collection ? collection.length : 0;
  
          if (typeof length == 'number') {
            while (++index < length) {
              var value = collection[index];
              setter(result, value, callback(value, index, collection), collection);
            }
          } else {
            forOwn(collection, function(value, key, collection) {
              setter(result, value, callback(value, key, collection), collection);
            });
          }
          return result;
        };
      }
  
      /**
       * Creates a function that, when called, either curries or invokes `func`
       * with an optional `this` binding and partially applied arguments.
       *
       * @private
       * @param {Function|string} func The function or method name to reference.
       * @param {number} bitmask The bitmask of method flags to compose.
       *  The bitmask may be composed of the following flags:
       *  1 - `_.bind`
       *  2 - `_.bindKey`
       *  4 - `_.curry`
       *  8 - `_.curry` (bound)
       *  16 - `_.partial`
       *  32 - `_.partialRight`
       * @param {Array} [partialArgs] An array of arguments to prepend to those
       *  provided to the new function.
       * @param {Array} [partialRightArgs] An array of arguments to append to those
       *  provided to the new function.
       * @param {*} [thisArg] The `this` binding of `func`.
       * @param {number} [arity] The arity of `func`.
       * @returns {Function} Returns the new function.
       */
      function createWrapper(func, bitmask, partialArgs, partialRightArgs, thisArg, arity) {
        var isBind = bitmask & 1,
            isBindKey = bitmask & 2,
            isCurry = bitmask & 4,
            isCurryBound = bitmask & 8,
            isPartial = bitmask & 16,
            isPartialRight = bitmask & 32;
  
        if (!isBindKey && !isFunction(func)) {
          throw new TypeError;
        }
        if (isPartial && !partialArgs.length) {
          bitmask &= ~16;
          isPartial = partialArgs = false;
        }
        if (isPartialRight && !partialRightArgs.length) {
          bitmask &= ~32;
          isPartialRight = partialRightArgs = false;
        }
        var bindData = func && func.__bindData__;
        if (bindData && bindData !== true) {
          // clone `bindData`
          bindData = slice(bindData);
          if (bindData[2]) {
            bindData[2] = slice(bindData[2]);
          }
          if (bindData[3]) {
            bindData[3] = slice(bindData[3]);
          }
          // set `thisBinding` is not previously bound
          if (isBind && !(bindData[1] & 1)) {
            bindData[4] = thisArg;
          }
          // set if previously bound but not currently (subsequent curried functions)
          if (!isBind && bindData[1] & 1) {
            bitmask |= 8;
          }
          // set curried arity if not yet set
          if (isCurry && !(bindData[1] & 4)) {
            bindData[5] = arity;
          }
          // append partial left arguments
          if (isPartial) {
            push.apply(bindData[2] || (bindData[2] = []), partialArgs);
          }
          // append partial right arguments
          if (isPartialRight) {
            unshift.apply(bindData[3] || (bindData[3] = []), partialRightArgs);
          }
          // merge flags
          bindData[1] |= bitmask;
          return createWrapper.apply(null, bindData);
        }
        // fast path for `_.bind`
        var creater = (bitmask == 1 || bitmask === 17) ? baseBind : baseCreateWrapper;
        return creater([func, bitmask, partialArgs, partialRightArgs, thisArg, arity]);
      }
  
      /**
       * Used by `escape` to convert characters to HTML entities.
       *
       * @private
       * @param {string} match The matched character to escape.
       * @returns {string} Returns the escaped character.
       */
      function escapeHtmlChar(match) {
        return htmlEscapes[match];
      }
  
      /**
       * Gets the appropriate "indexOf" function. If the `_.indexOf` method is
       * customized, this method returns the custom method, otherwise it returns
       * the `baseIndexOf` function.
       *
       * @private
       * @returns {Function} Returns the "indexOf" function.
       */
      function getIndexOf() {
        var result = (result = lodash.indexOf) === indexOf ? baseIndexOf : result;
        return result;
      }
  
      /**
       * Checks if `value` is a native function.
       *
       * @private
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is a native function, else `false`.
       */
      function isNative(value) {
        return typeof value == 'function' && reNative.test(value);
      }
  
      /**
       * Sets `this` binding data on a given function.
       *
       * @private
       * @param {Function} func The function to set data on.
       * @param {Array} value The data array to set.
       */
      var setBindData = !defineProperty ? noop : function(func, value) {
        descriptor.value = value;
        defineProperty(func, '__bindData__', descriptor);
      };
  
      /**
       * A fallback implementation of `isPlainObject` which checks if a given value
       * is an object created by the `Object` constructor, assuming objects created
       * by the `Object` constructor have no inherited enumerable properties and that
       * there are no `Object.prototype` extensions.
       *
       * @private
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
       */
      function shimIsPlainObject(value) {
        var ctor,
            result;
  
        // avoid non Object objects, `arguments` objects, and DOM elements
        if (!(value && toString.call(value) == objectClass) ||
            (ctor = value.constructor, isFunction(ctor) && !(ctor instanceof ctor))) {
          return false;
        }
        // In most environments an object's own properties are iterated before
        // its inherited properties. If the last iterated property is an object's
        // own property then there are no inherited enumerable properties.
        forIn(value, function(value, key) {
          result = key;
        });
        return typeof result == 'undefined' || hasOwnProperty.call(value, result);
      }
  
      /**
       * Used by `unescape` to convert HTML entities to characters.
       *
       * @private
       * @param {string} match The matched character to unescape.
       * @returns {string} Returns the unescaped character.
       */
      function unescapeHtmlChar(match) {
        return htmlUnescapes[match];
      }
  
      /*--------------------------------------------------------------------------*/
  
      /**
       * Checks if `value` is an `arguments` object.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is an `arguments` object, else `false`.
       * @example
       *
       * (function() { return _.isArguments(arguments); })(1, 2, 3);
       * // => true
       *
       * _.isArguments([1, 2, 3]);
       * // => false
       */
      function isArguments(value) {
        return value && typeof value == 'object' && typeof value.length == 'number' &&
          toString.call(value) == argsClass || false;
      }
  
      /**
       * Checks if `value` is an array.
       *
       * @static
       * @memberOf _
       * @type Function
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is an array, else `false`.
       * @example
       *
       * (function() { return _.isArray(arguments); })();
       * // => false
       *
       * _.isArray([1, 2, 3]);
       * // => true
       */
      var isArray = nativeIsArray || function(value) {
        return value && typeof value == 'object' && typeof value.length == 'number' &&
          toString.call(value) == arrayClass || false;
      };
  
      /**
       * A fallback implementation of `Object.keys` which produces an array of the
       * given object's own enumerable property names.
       *
       * @private
       * @type Function
       * @param {Object} object The object to inspect.
       * @returns {Array} Returns an array of property names.
       */
      var shimKeys = function(object) {
        var index, iterable = object, result = [];
        if (!iterable) return result;
        if (!(objectTypes[typeof object])) return result;
          for (index in iterable) {
            if (hasOwnProperty.call(iterable, index)) {
              result.push(index);
            }
          }
        return result
      };
  
      /**
       * Creates an array composed of the own enumerable property names of an object.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} object The object to inspect.
       * @returns {Array} Returns an array of property names.
       * @example
       *
       * _.keys({ 'one': 1, 'two': 2, 'three': 3 });
       * // => ['one', 'two', 'three'] (property order is not guaranteed across environments)
       */
      var keys = !nativeKeys ? shimKeys : function(object) {
        if (!isObject(object)) {
          return [];
        }
        return nativeKeys(object);
      };
  
      /**
       * Used to convert characters to HTML entities:
       *
       * Though the `>` character is escaped for symmetry, characters like `>` and `/`
       * don't require escaping in HTML and have no special meaning unless they're part
       * of a tag or an unquoted attribute value.
       * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact")
       */
      var htmlEscapes = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
        '"': '&quot;',
        "'": '&#39;'
      };
  
      /** Used to convert HTML entities to characters */
      var htmlUnescapes = invert(htmlEscapes);
  
      /** Used to match HTML entities and HTML characters */
      var reEscapedHtml = RegExp('(' + keys(htmlUnescapes).join('|') + ')', 'g'),
          reUnescapedHtml = RegExp('[' + keys(htmlEscapes).join('') + ']', 'g');
  
      /*--------------------------------------------------------------------------*/
  
      /**
       * Assigns own enumerable properties of source object(s) to the destination
       * object. Subsequent sources will overwrite property assignments of previous
       * sources. If a callback is provided it will be executed to produce the
       * assigned values. The callback is bound to `thisArg` and invoked with two
       * arguments; (objectValue, sourceValue).
       *
       * @static
       * @memberOf _
       * @type Function
       * @alias extend
       * @category Objects
       * @param {Object} object The destination object.
       * @param {...Object} [source] The source objects.
       * @param {Function} [callback] The function to customize assigning values.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Object} Returns the destination object.
       * @example
       *
       * _.assign({ 'name': 'fred' }, { 'employer': 'slate' });
       * // => { 'name': 'fred', 'employer': 'slate' }
       *
       * var defaults = _.partialRight(_.assign, function(a, b) {
       *   return typeof a == 'undefined' ? b : a;
       * });
       *
       * var object = { 'name': 'barney' };
       * defaults(object, { 'name': 'fred', 'employer': 'slate' });
       * // => { 'name': 'barney', 'employer': 'slate' }
       */
      var assign = function(object, source, guard) {
        var index, iterable = object, result = iterable;
        if (!iterable) return result;
        var args = arguments,
            argsIndex = 0,
            argsLength = typeof guard == 'number' ? 2 : args.length;
        if (argsLength > 3 && typeof args[argsLength - 2] == 'function') {
          var callback = baseCreateCallback(args[--argsLength - 1], args[argsLength--], 2);
        } else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {
          callback = args[--argsLength];
        }
        while (++argsIndex < argsLength) {
          iterable = args[argsIndex];
          if (iterable && objectTypes[typeof iterable]) {
          var ownIndex = -1,
              ownProps = objectTypes[typeof iterable] && keys(iterable),
              length = ownProps ? ownProps.length : 0;
  
          while (++ownIndex < length) {
            index = ownProps[ownIndex];
            result[index] = callback ? callback(result[index], iterable[index]) : iterable[index];
          }
          }
        }
        return result
      };
  
      /**
       * Creates a clone of `value`. If `isDeep` is `true` nested objects will also
       * be cloned, otherwise they will be assigned by reference. If a callback
       * is provided it will be executed to produce the cloned values. If the
       * callback returns `undefined` cloning will be handled by the method instead.
       * The callback is bound to `thisArg` and invoked with one argument; (value).
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to clone.
       * @param {boolean} [isDeep=false] Specify a deep clone.
       * @param {Function} [callback] The function to customize cloning values.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {*} Returns the cloned value.
       * @example
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 36 },
       *   { 'name': 'fred',   'age': 40 }
       * ];
       *
       * var shallow = _.clone(characters);
       * shallow[0] === characters[0];
       * // => true
       *
       * var deep = _.clone(characters, true);
       * deep[0] === characters[0];
       * // => false
       *
       * _.mixin({
       *   'clone': _.partialRight(_.clone, function(value) {
       *     return _.isElement(value) ? value.cloneNode(false) : undefined;
       *   })
       * });
       *
       * var clone = _.clone(document.body);
       * clone.childNodes.length;
       * // => 0
       */
      function clone(value, isDeep, callback, thisArg) {
        // allows working with "Collections" methods without using their `index`
        // and `collection` arguments for `isDeep` and `callback`
        if (typeof isDeep != 'boolean' && isDeep != null) {
          thisArg = callback;
          callback = isDeep;
          isDeep = false;
        }
        return baseClone(value, isDeep, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1));
      }
  
      /**
       * Creates a deep clone of `value`. If a callback is provided it will be
       * executed to produce the cloned values. If the callback returns `undefined`
       * cloning will be handled by the method instead. The callback is bound to
       * `thisArg` and invoked with one argument; (value).
       *
       * Note: This method is loosely based on the structured clone algorithm. Functions
       * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and
       * objects created by constructors other than `Object` are cloned to plain `Object` objects.
       * See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to deep clone.
       * @param {Function} [callback] The function to customize cloning values.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {*} Returns the deep cloned value.
       * @example
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 36 },
       *   { 'name': 'fred',   'age': 40 }
       * ];
       *
       * var deep = _.cloneDeep(characters);
       * deep[0] === characters[0];
       * // => false
       *
       * var view = {
       *   'label': 'docs',
       *   'node': element
       * };
       *
       * var clone = _.cloneDeep(view, function(value) {
       *   return _.isElement(value) ? value.cloneNode(true) : undefined;
       * });
       *
       * clone.node == view.node;
       * // => false
       */
      function cloneDeep(value, callback, thisArg) {
        return baseClone(value, true, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1));
      }
  
      /**
       * Creates an object that inherits from the given `prototype` object. If a
       * `properties` object is provided its own enumerable properties are assigned
       * to the created object.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} prototype The object to inherit from.
       * @param {Object} [properties] The properties to assign to the object.
       * @returns {Object} Returns the new object.
       * @example
       *
       * function Shape() {
       *   this.x = 0;
       *   this.y = 0;
       * }
       *
       * function Circle() {
       *   Shape.call(this);
       * }
       *
       * Circle.prototype = _.create(Shape.prototype, { 'constructor': Circle });
       *
       * var circle = new Circle;
       * circle instanceof Circle;
       * // => true
       *
       * circle instanceof Shape;
       * // => true
       */
      function create(prototype, properties) {
        var result = baseCreate(prototype);
        return properties ? assign(result, properties) : result;
      }
  
      /**
       * Assigns own enumerable properties of source object(s) to the destination
       * object for all destination properties that resolve to `undefined`. Once a
       * property is set, additional defaults of the same property will be ignored.
       *
       * @static
       * @memberOf _
       * @type Function
       * @category Objects
       * @param {Object} object The destination object.
       * @param {...Object} [source] The source objects.
       * @param- {Object} [guard] Allows working with `_.reduce` without using its
       *  `key` and `object` arguments as sources.
       * @returns {Object} Returns the destination object.
       * @example
       *
       * var object = { 'name': 'barney' };
       * _.defaults(object, { 'name': 'fred', 'employer': 'slate' });
       * // => { 'name': 'barney', 'employer': 'slate' }
       */
      var defaults = function(object, source, guard) {
        var index, iterable = object, result = iterable;
        if (!iterable) return result;
        var args = arguments,
            argsIndex = 0,
            argsLength = typeof guard == 'number' ? 2 : args.length;
        while (++argsIndex < argsLength) {
          iterable = args[argsIndex];
          if (iterable && objectTypes[typeof iterable]) {
          var ownIndex = -1,
              ownProps = objectTypes[typeof iterable] && keys(iterable),
              length = ownProps ? ownProps.length : 0;
  
          while (++ownIndex < length) {
            index = ownProps[ownIndex];
            if (typeof result[index] == 'undefined') result[index] = iterable[index];
          }
          }
        }
        return result
      };
  
      /**
       * This method is like `_.findIndex` except that it returns the key of the
       * first element that passes the callback check, instead of the element itself.
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} object The object to search.
       * @param {Function|Object|string} [callback=identity] The function called per
       *  iteration. If a property name or object is provided it will be used to
       *  create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {string|undefined} Returns the key of the found element, else `undefined`.
       * @example
       *
       * var characters = {
       *   'barney': {  'age': 36, 'blocked': false },
       *   'fred': {    'age': 40, 'blocked': true },
       *   'pebbles': { 'age': 1,  'blocked': false }
       * };
       *
       * _.findKey(characters, function(chr) {
       *   return chr.age < 40;
       * });
       * // => 'barney' (property order is not guaranteed across environments)
       *
       * // using "_.where" callback shorthand
       * _.findKey(characters, { 'age': 1 });
       * // => 'pebbles'
       *
       * // using "_.pluck" callback shorthand
       * _.findKey(characters, 'blocked');
       * // => 'fred'
       */
      function findKey(object, callback, thisArg) {
        var result;
        callback = lodash.createCallback(callback, thisArg, 3);
        forOwn(object, function(value, key, object) {
          if (callback(value, key, object)) {
            result = key;
            return false;
          }
        });
        return result;
      }
  
      /**
       * This method is like `_.findKey` except that it iterates over elements
       * of a `collection` in the opposite order.
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} object The object to search.
       * @param {Function|Object|string} [callback=identity] The function called per
       *  iteration. If a property name or object is provided it will be used to
       *  create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {string|undefined} Returns the key of the found element, else `undefined`.
       * @example
       *
       * var characters = {
       *   'barney': {  'age': 36, 'blocked': true },
       *   'fred': {    'age': 40, 'blocked': false },
       *   'pebbles': { 'age': 1,  'blocked': true }
       * };
       *
       * _.findLastKey(characters, function(chr) {
       *   return chr.age < 40;
       * });
       * // => returns `pebbles`, assuming `_.findKey` returns `barney`
       *
       * // using "_.where" callback shorthand
       * _.findLastKey(characters, { 'age': 40 });
       * // => 'fred'
       *
       * // using "_.pluck" callback shorthand
       * _.findLastKey(characters, 'blocked');
       * // => 'pebbles'
       */
      function findLastKey(object, callback, thisArg) {
        var result;
        callback = lodash.createCallback(callback, thisArg, 3);
        forOwnRight(object, function(value, key, object) {
          if (callback(value, key, object)) {
            result = key;
            return false;
          }
        });
        return result;
      }
  
      /**
       * Iterates over own and inherited enumerable properties of an object,
       * executing the callback for each property. The callback is bound to `thisArg`
       * and invoked with three arguments; (value, key, object). Callbacks may exit
       * iteration early by explicitly returning `false`.
       *
       * @static
       * @memberOf _
       * @type Function
       * @category Objects
       * @param {Object} object The object to iterate over.
       * @param {Function} [callback=identity] The function called per iteration.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Object} Returns `object`.
       * @example
       *
       * function Shape() {
       *   this.x = 0;
       *   this.y = 0;
       * }
       *
       * Shape.prototype.move = function(x, y) {
       *   this.x += x;
       *   this.y += y;
       * };
       *
       * _.forIn(new Shape, function(value, key) {
       *   console.log(key);
       * });
       * // => logs 'x', 'y', and 'move' (property order is not guaranteed across environments)
       */
      var forIn = function(collection, callback, thisArg) {
        var index, iterable = collection, result = iterable;
        if (!iterable) return result;
        if (!objectTypes[typeof iterable]) return result;
        callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
          for (index in iterable) {
            if (callback(iterable[index], index, collection) === false) return result;
          }
        return result
      };
  
      /**
       * This method is like `_.forIn` except that it iterates over elements
       * of a `collection` in the opposite order.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} object The object to iterate over.
       * @param {Function} [callback=identity] The function called per iteration.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Object} Returns `object`.
       * @example
       *
       * function Shape() {
       *   this.x = 0;
       *   this.y = 0;
       * }
       *
       * Shape.prototype.move = function(x, y) {
       *   this.x += x;
       *   this.y += y;
       * };
       *
       * _.forInRight(new Shape, function(value, key) {
       *   console.log(key);
       * });
       * // => logs 'move', 'y', and 'x' assuming `_.forIn ` logs 'x', 'y', and 'move'
       */
      function forInRight(object, callback, thisArg) {
        var pairs = [];
  
        forIn(object, function(value, key) {
          pairs.push(key, value);
        });
  
        var length = pairs.length;
        callback = baseCreateCallback(callback, thisArg, 3);
        while (length--) {
          if (callback(pairs[length--], pairs[length], object) === false) {
            break;
          }
        }
        return object;
      }
  
      /**
       * Iterates over own enumerable properties of an object, executing the callback
       * for each property. The callback is bound to `thisArg` and invoked with three
       * arguments; (value, key, object). Callbacks may exit iteration early by
       * explicitly returning `false`.
       *
       * @static
       * @memberOf _
       * @type Function
       * @category Objects
       * @param {Object} object The object to iterate over.
       * @param {Function} [callback=identity] The function called per iteration.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Object} Returns `object`.
       * @example
       *
       * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
       *   console.log(key);
       * });
       * // => logs '0', '1', and 'length' (property order is not guaranteed across environments)
       */
      var forOwn = function(collection, callback, thisArg) {
        var index, iterable = collection, result = iterable;
        if (!iterable) return result;
        if (!objectTypes[typeof iterable]) return result;
        callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
          var ownIndex = -1,
              ownProps = objectTypes[typeof iterable] && keys(iterable),
              length = ownProps ? ownProps.length : 0;
  
          while (++ownIndex < length) {
            index = ownProps[ownIndex];
            if (callback(iterable[index], index, collection) === false) return result;
          }
        return result
      };
  
      /**
       * This method is like `_.forOwn` except that it iterates over elements
       * of a `collection` in the opposite order.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} object The object to iterate over.
       * @param {Function} [callback=identity] The function called per iteration.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Object} Returns `object`.
       * @example
       *
       * _.forOwnRight({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
       *   console.log(key);
       * });
       * // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length'
       */
      function forOwnRight(object, callback, thisArg) {
        var props = keys(object),
            length = props.length;
  
        callback = baseCreateCallback(callback, thisArg, 3);
        while (length--) {
          var key = props[length];
          if (callback(object[key], key, object) === false) {
            break;
          }
        }
        return object;
      }
  
      /**
       * Creates a sorted array of property names of all enumerable properties,
       * own and inherited, of `object` that have function values.
       *
       * @static
       * @memberOf _
       * @alias methods
       * @category Objects
       * @param {Object} object The object to inspect.
       * @returns {Array} Returns an array of property names that have function values.
       * @example
       *
       * _.functions(_);
       * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
       */
      function functions(object) {
        var result = [];
        forIn(object, function(value, key) {
          if (isFunction(value)) {
            result.push(key);
          }
        });
        return result.sort();
      }
  
      /**
       * Checks if the specified property name exists as a direct property of `object`,
       * instead of an inherited property.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} object The object to inspect.
       * @param {string} key The name of the property to check.
       * @returns {boolean} Returns `true` if key is a direct property, else `false`.
       * @example
       *
       * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
       * // => true
       */
      function has(object, key) {
        return object ? hasOwnProperty.call(object, key) : false;
      }
  
      /**
       * Creates an object composed of the inverted keys and values of the given object.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} object The object to invert.
       * @returns {Object} Returns the created inverted object.
       * @example
       *
       * _.invert({ 'first': 'fred', 'second': 'barney' });
       * // => { 'fred': 'first', 'barney': 'second' }
       */
      function invert(object) {
        var index = -1,
            props = keys(object),
            length = props.length,
            result = {};
  
        while (++index < length) {
          var key = props[index];
          result[object[key]] = key;
        }
        return result;
      }
  
      /**
       * Checks if `value` is a boolean value.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is a boolean value, else `false`.
       * @example
       *
       * _.isBoolean(null);
       * // => false
       */
      function isBoolean(value) {
        return value === true || value === false ||
          value && typeof value == 'object' && toString.call(value) == boolClass || false;
      }
  
      /**
       * Checks if `value` is a date.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is a date, else `false`.
       * @example
       *
       * _.isDate(new Date);
       * // => true
       */
      function isDate(value) {
        return value && typeof value == 'object' && toString.call(value) == dateClass || false;
      }
  
      /**
       * Checks if `value` is a DOM element.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is a DOM element, else `false`.
       * @example
       *
       * _.isElement(document.body);
       * // => true
       */
      function isElement(value) {
        return value && value.nodeType === 1 || false;
      }
  
      /**
       * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
       * length of `0` and objects with no own enumerable properties are considered
       * "empty".
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Array|Object|string} value The value to inspect.
       * @returns {boolean} Returns `true` if the `value` is empty, else `false`.
       * @example
       *
       * _.isEmpty([1, 2, 3]);
       * // => false
       *
       * _.isEmpty({});
       * // => true
       *
       * _.isEmpty('');
       * // => true
       */
      function isEmpty(value) {
        var result = true;
        if (!value) {
          return result;
        }
        var className = toString.call(value),
            length = value.length;
  
        if ((className == arrayClass || className == stringClass || className == argsClass ) ||
            (className == objectClass && typeof length == 'number' && isFunction(value.splice))) {
          return !length;
        }
        forOwn(value, function() {
          return (result = false);
        });
        return result;
      }
  
      /**
       * Performs a deep comparison between two values to determine if they are
       * equivalent to each other. If a callback is provided it will be executed
       * to compare values. If the callback returns `undefined` comparisons will
       * be handled by the method instead. The callback is bound to `thisArg` and
       * invoked with two arguments; (a, b).
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} a The value to compare.
       * @param {*} b The other value to compare.
       * @param {Function} [callback] The function to customize comparing values.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
       * @example
       *
       * var object = { 'name': 'fred' };
       * var copy = { 'name': 'fred' };
       *
       * object == copy;
       * // => false
       *
       * _.isEqual(object, copy);
       * // => true
       *
       * var words = ['hello', 'goodbye'];
       * var otherWords = ['hi', 'goodbye'];
       *
       * _.isEqual(words, otherWords, function(a, b) {
       *   var reGreet = /^(?:hello|hi)$/i,
       *       aGreet = _.isString(a) && reGreet.test(a),
       *       bGreet = _.isString(b) && reGreet.test(b);
       *
       *   return (aGreet || bGreet) ? (aGreet == bGreet) : undefined;
       * });
       * // => true
       */
      function isEqual(a, b, callback, thisArg) {
        return baseIsEqual(a, b, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 2));
      }
  
      /**
       * Checks if `value` is, or can be coerced to, a finite number.
       *
       * Note: This is not the same as native `isFinite` which will return true for
       * booleans and empty strings. See http://es5.github.io/#x15.1.2.5.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is finite, else `false`.
       * @example
       *
       * _.isFinite(-101);
       * // => true
       *
       * _.isFinite('10');
       * // => true
       *
       * _.isFinite(true);
       * // => false
       *
       * _.isFinite('');
       * // => false
       *
       * _.isFinite(Infinity);
       * // => false
       */
      function isFinite(value) {
        return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value));
      }
  
      /**
       * Checks if `value` is a function.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is a function, else `false`.
       * @example
       *
       * _.isFunction(_);
       * // => true
       */
      function isFunction(value) {
        return typeof value == 'function';
      }
  
      /**
       * Checks if `value` is the language type of Object.
       * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is an object, else `false`.
       * @example
       *
       * _.isObject({});
       * // => true
       *
       * _.isObject([1, 2, 3]);
       * // => true
       *
       * _.isObject(1);
       * // => false
       */
      function isObject(value) {
        // check if the value is the ECMAScript language type of Object
        // http://es5.github.io/#x8
        // and avoid a V8 bug
        // http://code.google.com/p/v8/issues/detail?id=2291
        return !!(value && objectTypes[typeof value]);
      }
  
      /**
       * Checks if `value` is `NaN`.
       *
       * Note: This is not the same as native `isNaN` which will return `true` for
       * `undefined` and other non-numeric values. See http://es5.github.io/#x15.1.2.4.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is `NaN`, else `false`.
       * @example
       *
       * _.isNaN(NaN);
       * // => true
       *
       * _.isNaN(new Number(NaN));
       * // => true
       *
       * isNaN(undefined);
       * // => true
       *
       * _.isNaN(undefined);
       * // => false
       */
      function isNaN(value) {
        // `NaN` as a primitive is the only value that is not equal to itself
        // (perform the [[Class]] check first to avoid errors with some host objects in IE)
        return isNumber(value) && value != +value;
      }
  
      /**
       * Checks if `value` is `null`.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is `null`, else `false`.
       * @example
       *
       * _.isNull(null);
       * // => true
       *
       * _.isNull(undefined);
       * // => false
       */
      function isNull(value) {
        return value === null;
      }
  
      /**
       * Checks if `value` is a number.
       *
       * Note: `NaN` is considered a number. See http://es5.github.io/#x8.5.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is a number, else `false`.
       * @example
       *
       * _.isNumber(8.4 * 5);
       * // => true
       */
      function isNumber(value) {
        return typeof value == 'number' ||
          value && typeof value == 'object' && toString.call(value) == numberClass || false;
      }
  
      /**
       * Checks if `value` is an object created by the `Object` constructor.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
       * @example
       *
       * function Shape() {
       *   this.x = 0;
       *   this.y = 0;
       * }
       *
       * _.isPlainObject(new Shape);
       * // => false
       *
       * _.isPlainObject([1, 2, 3]);
       * // => false
       *
       * _.isPlainObject({ 'x': 0, 'y': 0 });
       * // => true
       */
      var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) {
        if (!(value && toString.call(value) == objectClass)) {
          return false;
        }
        var valueOf = value.valueOf,
            objProto = isNative(valueOf) && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto);
  
        return objProto
          ? (value == objProto || getPrototypeOf(value) == objProto)
          : shimIsPlainObject(value);
      };
  
      /**
       * Checks if `value` is a regular expression.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is a regular expression, else `false`.
       * @example
       *
       * _.isRegExp(/fred/);
       * // => true
       */
      function isRegExp(value) {
        return value && typeof value == 'object' && toString.call(value) == regexpClass || false;
      }
  
      /**
       * Checks if `value` is a string.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is a string, else `false`.
       * @example
       *
       * _.isString('fred');
       * // => true
       */
      function isString(value) {
        return typeof value == 'string' ||
          value && typeof value == 'object' && toString.call(value) == stringClass || false;
      }
  
      /**
       * Checks if `value` is `undefined`.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is `undefined`, else `false`.
       * @example
       *
       * _.isUndefined(void 0);
       * // => true
       */
      function isUndefined(value) {
        return typeof value == 'undefined';
      }
  
      /**
       * Creates an object with the same keys as `object` and values generated by
       * running each own enumerable property of `object` through the callback.
       * The callback is bound to `thisArg` and invoked with three arguments;
       * (value, key, object).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} object The object to iterate over.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Array} Returns a new object with values of the results of each `callback` execution.
       * @example
       *
       * _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(num) { return num * 3; });
       * // => { 'a': 3, 'b': 6, 'c': 9 }
       *
       * var characters = {
       *   'fred': { 'name': 'fred', 'age': 40 },
       *   'pebbles': { 'name': 'pebbles', 'age': 1 }
       * };
       *
       * // using "_.pluck" callback shorthand
       * _.mapValues(characters, 'age');
       * // => { 'fred': 40, 'pebbles': 1 }
       */
      function mapValues(object, callback, thisArg) {
        var result = {};
        callback = lodash.createCallback(callback, thisArg, 3);
  
        forOwn(object, function(value, key, object) {
          result[key] = callback(value, key, object);
        });
        return result;
      }
  
      /**
       * Recursively merges own enumerable properties of the source object(s), that
       * don't resolve to `undefined` into the destination object. Subsequent sources
       * will overwrite property assignments of previous sources. If a callback is
       * provided it will be executed to produce the merged values of the destination
       * and source properties. If the callback returns `undefined` merging will
       * be handled by the method instead. The callback is bound to `thisArg` and
       * invoked with two arguments; (objectValue, sourceValue).
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} object The destination object.
       * @param {...Object} [source] The source objects.
       * @param {Function} [callback] The function to customize merging properties.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Object} Returns the destination object.
       * @example
       *
       * var names = {
       *   'characters': [
       *     { 'name': 'barney' },
       *     { 'name': 'fred' }
       *   ]
       * };
       *
       * var ages = {
       *   'characters': [
       *     { 'age': 36 },
       *     { 'age': 40 }
       *   ]
       * };
       *
       * _.merge(names, ages);
       * // => { 'characters': [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }] }
       *
       * var food = {
       *   'fruits': ['apple'],
       *   'vegetables': ['beet']
       * };
       *
       * var otherFood = {
       *   'fruits': ['banana'],
       *   'vegetables': ['carrot']
       * };
       *
       * _.merge(food, otherFood, function(a, b) {
       *   return _.isArray(a) ? a.concat(b) : undefined;
       * });
       * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] }
       */
      function merge(object) {
        var args = arguments,
            length = 2;
  
        if (!isObject(object)) {
          return object;
        }
        // allows working with `_.reduce` and `_.reduceRight` without using
        // their `index` and `collection` arguments
        if (typeof args[2] != 'number') {
          length = args.length;
        }
        if (length > 3 && typeof args[length - 2] == 'function') {
          var callback = baseCreateCallback(args[--length - 1], args[length--], 2);
        } else if (length > 2 && typeof args[length - 1] == 'function') {
          callback = args[--length];
        }
        var sources = slice(arguments, 1, length),
            index = -1,
            stackA = getArray(),
            stackB = getArray();
  
        while (++index < length) {
          baseMerge(object, sources[index], callback, stackA, stackB);
        }
        releaseArray(stackA);
        releaseArray(stackB);
        return object;
      }
  
      /**
       * Creates a shallow clone of `object` excluding the specified properties.
       * Property names may be specified as individual arguments or as arrays of
       * property names. If a callback is provided it will be executed for each
       * property of `object` omitting the properties the callback returns truey
       * for. The callback is bound to `thisArg` and invoked with three arguments;
       * (value, key, object).
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} object The source object.
       * @param {Function|...string|string[]} [callback] The properties to omit or the
       *  function called per iteration.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Object} Returns an object without the omitted properties.
       * @example
       *
       * _.omit({ 'name': 'fred', 'age': 40 }, 'age');
       * // => { 'name': 'fred' }
       *
       * _.omit({ 'name': 'fred', 'age': 40 }, function(value) {
       *   return typeof value == 'number';
       * });
       * // => { 'name': 'fred' }
       */
      function omit(object, callback, thisArg) {
        var result = {};
        if (typeof callback != 'function') {
          var props = [];
          forIn(object, function(value, key) {
            props.push(key);
          });
          props = baseDifference(props, baseFlatten(arguments, true, false, 1));
  
          var index = -1,
              length = props.length;
  
          while (++index < length) {
            var key = props[index];
            result[key] = object[key];
          }
        } else {
          callback = lodash.createCallback(callback, thisArg, 3);
          forIn(object, function(value, key, object) {
            if (!callback(value, key, object)) {
              result[key] = value;
            }
          });
        }
        return result;
      }
  
      /**
       * Creates a two dimensional array of an object's key-value pairs,
       * i.e. `[[key1, value1], [key2, value2]]`.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} object The object to inspect.
       * @returns {Array} Returns new array of key-value pairs.
       * @example
       *
       * _.pairs({ 'barney': 36, 'fred': 40 });
       * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed across environments)
       */
      function pairs(object) {
        var index = -1,
            props = keys(object),
            length = props.length,
            result = Array(length);
  
        while (++index < length) {
          var key = props[index];
          result[index] = [key, object[key]];
        }
        return result;
      }
  
      /**
       * Creates a shallow clone of `object` composed of the specified properties.
       * Property names may be specified as individual arguments or as arrays of
       * property names. If a callback is provided it will be executed for each
       * property of `object` picking the properties the callback returns truey
       * for. The callback is bound to `thisArg` and invoked with three arguments;
       * (value, key, object).
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} object The source object.
       * @param {Function|...string|string[]} [callback] The function called per
       *  iteration or property names to pick, specified as individual property
       *  names or arrays of property names.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Object} Returns an object composed of the picked properties.
       * @example
       *
       * _.pick({ 'name': 'fred', '_userid': 'fred1' }, 'name');
       * // => { 'name': 'fred' }
       *
       * _.pick({ 'name': 'fred', '_userid': 'fred1' }, function(value, key) {
       *   return key.charAt(0) != '_';
       * });
       * // => { 'name': 'fred' }
       */
      function pick(object, callback, thisArg) {
        var result = {};
        if (typeof callback != 'function') {
          var index = -1,
              props = baseFlatten(arguments, true, false, 1),
              length = isObject(object) ? props.length : 0;
  
          while (++index < length) {
            var key = props[index];
            if (key in object) {
              result[key] = object[key];
            }
          }
        } else {
          callback = lodash.createCallback(callback, thisArg, 3);
          forIn(object, function(value, key, object) {
            if (callback(value, key, object)) {
              result[key] = value;
            }
          });
        }
        return result;
      }
  
      /**
       * An alternative to `_.reduce` this method transforms `object` to a new
       * `accumulator` object which is the result of running each of its own
       * enumerable properties through a callback, with each callback execution
       * potentially mutating the `accumulator` object. The callback is bound to
       * `thisArg` and invoked with four arguments; (accumulator, value, key, object).
       * Callbacks may exit iteration early by explicitly returning `false`.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Array|Object} object The object to iterate over.
       * @param {Function} [callback=identity] The function called per iteration.
       * @param {*} [accumulator] The custom accumulator value.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {*} Returns the accumulated value.
       * @example
       *
       * var squares = _.transform([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function(result, num) {
       *   num *= num;
       *   if (num % 2) {
       *     return result.push(num) < 3;
       *   }
       * });
       * // => [1, 9, 25]
       *
       * var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
       *   result[key] = num * 3;
       * });
       * // => { 'a': 3, 'b': 6, 'c': 9 }
       */
      function transform(object, callback, accumulator, thisArg) {
        var isArr = isArray(object);
        if (accumulator == null) {
          if (isArr) {
            accumulator = [];
          } else {
            var ctor = object && object.constructor,
                proto = ctor && ctor.prototype;
  
            accumulator = baseCreate(proto);
          }
        }
        if (callback) {
          callback = lodash.createCallback(callback, thisArg, 4);
          (isArr ? forEach : forOwn)(object, function(value, index, object) {
            return callback(accumulator, value, index, object);
          });
        }
        return accumulator;
      }
  
      /**
       * Creates an array composed of the own enumerable property values of `object`.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} object The object to inspect.
       * @returns {Array} Returns an array of property values.
       * @example
       *
       * _.values({ 'one': 1, 'two': 2, 'three': 3 });
       * // => [1, 2, 3] (property order is not guaranteed across environments)
       */
      function values(object) {
        var index = -1,
            props = keys(object),
            length = props.length,
            result = Array(length);
  
        while (++index < length) {
          result[index] = object[props[index]];
        }
        return result;
      }
  
      /*--------------------------------------------------------------------------*/
  
      /**
       * Creates an array of elements from the specified indexes, or keys, of the
       * `collection`. Indexes may be specified as individual arguments or as arrays
       * of indexes.
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {...(number|number[]|string|string[])} [index] The indexes of `collection`
       *   to retrieve, specified as individual indexes or arrays of indexes.
       * @returns {Array} Returns a new array of elements corresponding to the
       *  provided indexes.
       * @example
       *
       * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]);
       * // => ['a', 'c', 'e']
       *
       * _.at(['fred', 'barney', 'pebbles'], 0, 2);
       * // => ['fred', 'pebbles']
       */
      function at(collection) {
        var args = arguments,
            index = -1,
            props = baseFlatten(args, true, false, 1),
            length = (args[2] && args[2][args[1]] === collection) ? 1 : props.length,
            result = Array(length);
  
        while(++index < length) {
          result[index] = collection[props[index]];
        }
        return result;
      }
  
      /**
       * Checks if a given value is present in a collection using strict equality
       * for comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the
       * offset from the end of the collection.
       *
       * @static
       * @memberOf _
       * @alias include
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {*} target The value to check for.
       * @param {number} [fromIndex=0] The index to search from.
       * @returns {boolean} Returns `true` if the `target` element is found, else `false`.
       * @example
       *
       * _.contains([1, 2, 3], 1);
       * // => true
       *
       * _.contains([1, 2, 3], 1, 2);
       * // => false
       *
       * _.contains({ 'name': 'fred', 'age': 40 }, 'fred');
       * // => true
       *
       * _.contains('pebbles', 'eb');
       * // => true
       */
      function contains(collection, target, fromIndex) {
        var index = -1,
            indexOf = getIndexOf(),
            length = collection ? collection.length : 0,
            result = false;
  
        fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0;
        if (isArray(collection)) {
          result = indexOf(collection, target, fromIndex) > -1;
        } else if (typeof length == 'number') {
          result = (isString(collection) ? collection.indexOf(target, fromIndex) : indexOf(collection, target, fromIndex)) > -1;
        } else {
          forOwn(collection, function(value) {
            if (++index >= fromIndex) {
              return !(result = value === target);
            }
          });
        }
        return result;
      }
  
      /**
       * Creates an object composed of keys generated from the results of running
       * each element of `collection` through the callback. The corresponding value
       * of each key is the number of times the key was returned by the callback.
       * The callback is bound to `thisArg` and invoked with three arguments;
       * (value, index|key, collection).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Object} Returns the composed aggregate object.
       * @example
       *
       * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); });
       * // => { '4': 1, '6': 2 }
       *
       * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
       * // => { '4': 1, '6': 2 }
       *
       * _.countBy(['one', 'two', 'three'], 'length');
       * // => { '3': 2, '5': 1 }
       */
      var countBy = createAggregator(function(result, value, key) {
        (hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1);
      });
  
      /**
       * Checks if the given callback returns truey value for **all** elements of
       * a collection. The callback is bound to `thisArg` and invoked with three
       * arguments; (value, index|key, collection).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @alias all
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {boolean} Returns `true` if all elements passed the callback check,
       *  else `false`.
       * @example
       *
       * _.every([true, 1, null, 'yes']);
       * // => false
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 36 },
       *   { 'name': 'fred',   'age': 40 }
       * ];
       *
       * // using "_.pluck" callback shorthand
       * _.every(characters, 'age');
       * // => true
       *
       * // using "_.where" callback shorthand
       * _.every(characters, { 'age': 36 });
       * // => false
       */
      function every(collection, callback, thisArg) {
        var result = true;
        callback = lodash.createCallback(callback, thisArg, 3);
  
        var index = -1,
            length = collection ? collection.length : 0;
  
        if (typeof length == 'number') {
          while (++index < length) {
            if (!(result = !!callback(collection[index], index, collection))) {
              break;
            }
          }
        } else {
          forOwn(collection, function(value, index, collection) {
            return (result = !!callback(value, index, collection));
          });
        }
        return result;
      }
  
      /**
       * Iterates over elements of a collection, returning an array of all elements
       * the callback returns truey for. The callback is bound to `thisArg` and
       * invoked with three arguments; (value, index|key, collection).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @alias select
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Array} Returns a new array of elements that passed the callback check.
       * @example
       *
       * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
       * // => [2, 4, 6]
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 36, 'blocked': false },
       *   { 'name': 'fred',   'age': 40, 'blocked': true }
       * ];
       *
       * // using "_.pluck" callback shorthand
       * _.filter(characters, 'blocked');
       * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
       *
       * // using "_.where" callback shorthand
       * _.filter(characters, { 'age': 36 });
       * // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
       */
      function filter(collection, callback, thisArg) {
        var result = [];
        callback = lodash.createCallback(callback, thisArg, 3);
  
        var index = -1,
            length = collection ? collection.length : 0;
  
        if (typeof length == 'number') {
          while (++index < length) {
            var value = collection[index];
            if (callback(value, index, collection)) {
              result.push(value);
            }
          }
        } else {
          forOwn(collection, function(value, index, collection) {
            if (callback(value, index, collection)) {
              result.push(value);
            }
          });
        }
        return result;
      }
  
      /**
       * Iterates over elements of a collection, returning the first element that
       * the callback returns truey for. The callback is bound to `thisArg` and
       * invoked with three arguments; (value, index|key, collection).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @alias detect, findWhere
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {*} Returns the found element, else `undefined`.
       * @example
       *
       * var characters = [
       *   { 'name': 'barney',  'age': 36, 'blocked': false },
       *   { 'name': 'fred',    'age': 40, 'blocked': true },
       *   { 'name': 'pebbles', 'age': 1,  'blocked': false }
       * ];
       *
       * _.find(characters, function(chr) {
       *   return chr.age < 40;
       * });
       * // => { 'name': 'barney', 'age': 36, 'blocked': false }
       *
       * // using "_.where" callback shorthand
       * _.find(characters, { 'age': 1 });
       * // =>  { 'name': 'pebbles', 'age': 1, 'blocked': false }
       *
       * // using "_.pluck" callback shorthand
       * _.find(characters, 'blocked');
       * // => { 'name': 'fred', 'age': 40, 'blocked': true }
       */
      function find(collection, callback, thisArg) {
        callback = lodash.createCallback(callback, thisArg, 3);
  
        var index = -1,
            length = collection ? collection.length : 0;
  
        if (typeof length == 'number') {
          while (++index < length) {
            var value = collection[index];
            if (callback(value, index, collection)) {
              return value;
            }
          }
        } else {
          var result;
          forOwn(collection, function(value, index, collection) {
            if (callback(value, index, collection)) {
              result = value;
              return false;
            }
          });
          return result;
        }
      }
  
      /**
       * This method is like `_.find` except that it iterates over elements
       * of a `collection` from right to left.
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {*} Returns the found element, else `undefined`.
       * @example
       *
       * _.findLast([1, 2, 3, 4], function(num) {
       *   return num % 2 == 1;
       * });
       * // => 3
       */
      function findLast(collection, callback, thisArg) {
        var result;
        callback = lodash.createCallback(callback, thisArg, 3);
        forEachRight(collection, function(value, index, collection) {
          if (callback(value, index, collection)) {
            result = value;
            return false;
          }
        });
        return result;
      }
  
      /**
       * Iterates over elements of a collection, executing the callback for each
       * element. The callback is bound to `thisArg` and invoked with three arguments;
       * (value, index|key, collection). Callbacks may exit iteration early by
       * explicitly returning `false`.
       *
       * Note: As with other "Collections" methods, objects with a `length` property
       * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn`
       * may be used for object iteration.
       *
       * @static
       * @memberOf _
       * @alias each
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function} [callback=identity] The function called per iteration.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Array|Object|string} Returns `collection`.
       * @example
       *
       * _([1, 2, 3]).forEach(function(num) { console.log(num); }).join(',');
       * // => logs each number and returns '1,2,3'
       *
       * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); });
       * // => logs each number and returns the object (property order is not guaranteed across environments)
       */
      function forEach(collection, callback, thisArg) {
        var index = -1,
            length = collection ? collection.length : 0;
  
        callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
        if (typeof length == 'number') {
          while (++index < length) {
            if (callback(collection[index], index, collection) === false) {
              break;
            }
          }
        } else {
          forOwn(collection, callback);
        }
        return collection;
      }
  
      /**
       * This method is like `_.forEach` except that it iterates over elements
       * of a `collection` from right to left.
       *
       * @static
       * @memberOf _
       * @alias eachRight
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function} [callback=identity] The function called per iteration.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Array|Object|string} Returns `collection`.
       * @example
       *
       * _([1, 2, 3]).forEachRight(function(num) { console.log(num); }).join(',');
       * // => logs each number from right to left and returns '3,2,1'
       */
      function forEachRight(collection, callback, thisArg) {
        var length = collection ? collection.length : 0;
        callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
        if (typeof length == 'number') {
          while (length--) {
            if (callback(collection[length], length, collection) === false) {
              break;
            }
          }
        } else {
          var props = keys(collection);
          length = props.length;
          forOwn(collection, function(value, key, collection) {
            key = props ? props[--length] : --length;
            return callback(collection[key], key, collection);
          });
        }
        return collection;
      }
  
      /**
       * Creates an object composed of keys generated from the results of running
       * each element of a collection through the callback. The corresponding value
       * of each key is an array of the elements responsible for generating the key.
       * The callback is bound to `thisArg` and invoked with three arguments;
       * (value, index|key, collection).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Object} Returns the composed aggregate object.
       * @example
       *
       * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); });
       * // => { '4': [4.2], '6': [6.1, 6.4] }
       *
       * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
       * // => { '4': [4.2], '6': [6.1, 6.4] }
       *
       * // using "_.pluck" callback shorthand
       * _.groupBy(['one', 'two', 'three'], 'length');
       * // => { '3': ['one', 'two'], '5': ['three'] }
       */
      var groupBy = createAggregator(function(result, value, key) {
        (hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value);
      });
  
      /**
       * Creates an object composed of keys generated from the results of running
       * each element of the collection through the given callback. The corresponding
       * value of each key is the last element responsible for generating the key.
       * The callback is bound to `thisArg` and invoked with three arguments;
       * (value, index|key, collection).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Object} Returns the composed aggregate object.
       * @example
       *
       * var keys = [
       *   { 'dir': 'left', 'code': 97 },
       *   { 'dir': 'right', 'code': 100 }
       * ];
       *
       * _.indexBy(keys, 'dir');
       * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
       *
       * _.indexBy(keys, function(key) { return String.fromCharCode(key.code); });
       * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
       *
       * _.indexBy(characters, function(key) { this.fromCharCode(key.code); }, String);
       * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
       */
      var indexBy = createAggregator(function(result, value, key) {
        result[key] = value;
      });
  
      /**
       * Invokes the method named by `methodName` on each element in the `collection`
       * returning an array of the results of each invoked method. Additional arguments
       * will be provided to each invoked method. If `methodName` is a function it
       * will be invoked for, and `this` bound to, each element in the `collection`.
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function|string} methodName The name of the method to invoke or
       *  the function invoked per iteration.
       * @param {...*} [arg] Arguments to invoke the method with.
       * @returns {Array} Returns a new array of the results of each invoked method.
       * @example
       *
       * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
       * // => [[1, 5, 7], [1, 2, 3]]
       *
       * _.invoke([123, 456], String.prototype.split, '');
       * // => [['1', '2', '3'], ['4', '5', '6']]
       */
      function invoke(collection, methodName) {
        var args = slice(arguments, 2),
            index = -1,
            isFunc = typeof methodName == 'function',
            length = collection ? collection.length : 0,
            result = Array(typeof length == 'number' ? length : 0);
  
        forEach(collection, function(value) {
          result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args);
        });
        return result;
      }
  
      /**
       * Creates an array of values by running each element in the collection
       * through the callback. The callback is bound to `thisArg` and invoked with
       * three arguments; (value, index|key, collection).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @alias collect
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Array} Returns a new array of the results of each `callback` execution.
       * @example
       *
       * _.map([1, 2, 3], function(num) { return num * 3; });
       * // => [3, 6, 9]
       *
       * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
       * // => [3, 6, 9] (property order is not guaranteed across environments)
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 36 },
       *   { 'name': 'fred',   'age': 40 }
       * ];
       *
       * // using "_.pluck" callback shorthand
       * _.map(characters, 'name');
       * // => ['barney', 'fred']
       */
      function map(collection, callback, thisArg) {
        var index = -1,
            length = collection ? collection.length : 0;
  
        callback = lodash.createCallback(callback, thisArg, 3);
        if (typeof length == 'number') {
          var result = Array(length);
          while (++index < length) {
            result[index] = callback(collection[index], index, collection);
          }
        } else {
          result = [];
          forOwn(collection, function(value, key, collection) {
            result[++index] = callback(value, key, collection);
          });
        }
        return result;
      }
  
      /**
       * Retrieves the maximum value of a collection. If the collection is empty or
       * falsey `-Infinity` is returned. If a callback is provided it will be executed
       * for each value in the collection to generate the criterion by which the value
       * is ranked. The callback is bound to `thisArg` and invoked with three
       * arguments; (value, index, collection).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {*} Returns the maximum value.
       * @example
       *
       * _.max([4, 2, 8, 6]);
       * // => 8
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 36 },
       *   { 'name': 'fred',   'age': 40 }
       * ];
       *
       * _.max(characters, function(chr) { return chr.age; });
       * // => { 'name': 'fred', 'age': 40 };
       *
       * // using "_.pluck" callback shorthand
       * _.max(characters, 'age');
       * // => { 'name': 'fred', 'age': 40 };
       */
      function max(collection, callback, thisArg) {
        var computed = -Infinity,
            result = computed;
  
        // allows working with functions like `_.map` without using
        // their `index` argument as a callback
        if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) {
          callback = null;
        }
        if (callback == null && isArray(collection)) {
          var index = -1,
              length = collection.length;
  
          while (++index < length) {
            var value = collection[index];
            if (value > result) {
              result = value;
            }
          }
        } else {
          callback = (callback == null && isString(collection))
            ? charAtCallback
            : lodash.createCallback(callback, thisArg, 3);
  
          forEach(collection, function(value, index, collection) {
            var current = callback(value, index, collection);
            if (current > computed) {
              computed = current;
              result = value;
            }
          });
        }
        return result;
      }
  
      /**
       * Retrieves the minimum value of a collection. If the collection is empty or
       * falsey `Infinity` is returned. If a callback is provided it will be executed
       * for each value in the collection to generate the criterion by which the value
       * is ranked. The callback is bound to `thisArg` and invoked with three
       * arguments; (value, index, collection).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {*} Returns the minimum value.
       * @example
       *
       * _.min([4, 2, 8, 6]);
       * // => 2
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 36 },
       *   { 'name': 'fred',   'age': 40 }
       * ];
       *
       * _.min(characters, function(chr) { return chr.age; });
       * // => { 'name': 'barney', 'age': 36 };
       *
       * // using "_.pluck" callback shorthand
       * _.min(characters, 'age');
       * // => { 'name': 'barney', 'age': 36 };
       */
      function min(collection, callback, thisArg) {
        var computed = Infinity,
            result = computed;
  
        // allows working with functions like `_.map` without using
        // their `index` argument as a callback
        if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) {
          callback = null;
        }
        if (callback == null && isArray(collection)) {
          var index = -1,
              length = collection.length;
  
          while (++index < length) {
            var value = collection[index];
            if (value < result) {
              result = value;
            }
          }
        } else {
          callback = (callback == null && isString(collection))
            ? charAtCallback
            : lodash.createCallback(callback, thisArg, 3);
  
          forEach(collection, function(value, index, collection) {
            var current = callback(value, index, collection);
            if (current < computed) {
              computed = current;
              result = value;
            }
          });
        }
        return result;
      }
  
      /**
       * Retrieves the value of a specified property from all elements in the collection.
       *
       * @static
       * @memberOf _
       * @type Function
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {string} property The name of the property to pluck.
       * @returns {Array} Returns a new array of property values.
       * @example
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 36 },
       *   { 'name': 'fred',   'age': 40 }
       * ];
       *
       * _.pluck(characters, 'name');
       * // => ['barney', 'fred']
       */
      var pluck = map;
  
      /**
       * Reduces a collection to a value which is the accumulated result of running
       * each element in the collection through the callback, where each successive
       * callback execution consumes the return value of the previous execution. If
       * `accumulator` is not provided the first element of the collection will be
       * used as the initial `accumulator` value. The callback is bound to `thisArg`
       * and invoked with four arguments; (accumulator, value, index|key, collection).
       *
       * @static
       * @memberOf _
       * @alias foldl, inject
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function} [callback=identity] The function called per iteration.
       * @param {*} [accumulator] Initial value of the accumulator.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {*} Returns the accumulated value.
       * @example
       *
       * var sum = _.reduce([1, 2, 3], function(sum, num) {
       *   return sum + num;
       * });
       * // => 6
       *
       * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
       *   result[key] = num * 3;
       *   return result;
       * }, {});
       * // => { 'a': 3, 'b': 6, 'c': 9 }
       */
      function reduce(collection, callback, accumulator, thisArg) {
        if (!collection) return accumulator;
        var noaccum = arguments.length < 3;
        callback = lodash.createCallback(callback, thisArg, 4);
  
        var index = -1,
            length = collection.length;
  
        if (typeof length == 'number') {
          if (noaccum) {
            accumulator = collection[++index];
          }
          while (++index < length) {
            accumulator = callback(accumulator, collection[index], index, collection);
          }
        } else {
          forOwn(collection, function(value, index, collection) {
            accumulator = noaccum
              ? (noaccum = false, value)
              : callback(accumulator, value, index, collection)
          });
        }
        return accumulator;
      }
  
      /**
       * This method is like `_.reduce` except that it iterates over elements
       * of a `collection` from right to left.
       *
       * @static
       * @memberOf _
       * @alias foldr
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function} [callback=identity] The function called per iteration.
       * @param {*} [accumulator] Initial value of the accumulator.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {*} Returns the accumulated value.
       * @example
       *
       * var list = [[0, 1], [2, 3], [4, 5]];
       * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
       * // => [4, 5, 2, 3, 0, 1]
       */
      function reduceRight(collection, callback, accumulator, thisArg) {
        var noaccum = arguments.length < 3;
        callback = lodash.createCallback(callback, thisArg, 4);
        forEachRight(collection, function(value, index, collection) {
          accumulator = noaccum
            ? (noaccum = false, value)
            : callback(accumulator, value, index, collection);
        });
        return accumulator;
      }
  
      /**
       * The opposite of `_.filter` this method returns the elements of a
       * collection that the callback does **not** return truey for.
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Array} Returns a new array of elements that failed the callback check.
       * @example
       *
       * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
       * // => [1, 3, 5]
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 36, 'blocked': false },
       *   { 'name': 'fred',   'age': 40, 'blocked': true }
       * ];
       *
       * // using "_.pluck" callback shorthand
       * _.reject(characters, 'blocked');
       * // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
       *
       * // using "_.where" callback shorthand
       * _.reject(characters, { 'age': 36 });
       * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
       */
      function reject(collection, callback, thisArg) {
        callback = lodash.createCallback(callback, thisArg, 3);
        return filter(collection, function(value, index, collection) {
          return !callback(value, index, collection);
        });
      }
  
      /**
       * Retrieves a random element or `n` random elements from a collection.
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to sample.
       * @param {number} [n] The number of elements to sample.
       * @param- {Object} [guard] Allows working with functions like `_.map`
       *  without using their `index` arguments as `n`.
       * @returns {Array} Returns the random sample(s) of `collection`.
       * @example
       *
       * _.sample([1, 2, 3, 4]);
       * // => 2
       *
       * _.sample([1, 2, 3, 4], 2);
       * // => [3, 1]
       */
      function sample(collection, n, guard) {
        if (collection && typeof collection.length != 'number') {
          collection = values(collection);
        }
        if (n == null || guard) {
          return collection ? collection[baseRandom(0, collection.length - 1)] : undefined;
        }
        var result = shuffle(collection);
        result.length = nativeMin(nativeMax(0, n), result.length);
        return result;
      }
  
      /**
       * Creates an array of shuffled values, using a version of the Fisher-Yates
       * shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to shuffle.
       * @returns {Array} Returns a new shuffled collection.
       * @example
       *
       * _.shuffle([1, 2, 3, 4, 5, 6]);
       * // => [4, 1, 6, 3, 5, 2]
       */
      function shuffle(collection) {
        var index = -1,
            length = collection ? collection.length : 0,
            result = Array(typeof length == 'number' ? length : 0);
  
        forEach(collection, function(value) {
          var rand = baseRandom(0, ++index);
          result[index] = result[rand];
          result[rand] = value;
        });
        return result;
      }
  
      /**
       * Gets the size of the `collection` by returning `collection.length` for arrays
       * and array-like objects or the number of own enumerable properties for objects.
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to inspect.
       * @returns {number} Returns `collection.length` or number of own enumerable properties.
       * @example
       *
       * _.size([1, 2]);
       * // => 2
       *
       * _.size({ 'one': 1, 'two': 2, 'three': 3 });
       * // => 3
       *
       * _.size('pebbles');
       * // => 7
       */
      function size(collection) {
        var length = collection ? collection.length : 0;
        return typeof length == 'number' ? length : keys(collection).length;
      }
  
      /**
       * Checks if the callback returns a truey value for **any** element of a
       * collection. The function returns as soon as it finds a passing value and
       * does not iterate over the entire collection. The callback is bound to
       * `thisArg` and invoked with three arguments; (value, index|key, collection).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @alias any
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {boolean} Returns `true` if any element passed the callback check,
       *  else `false`.
       * @example
       *
       * _.some([null, 0, 'yes', false], Boolean);
       * // => true
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 36, 'blocked': false },
       *   { 'name': 'fred',   'age': 40, 'blocked': true }
       * ];
       *
       * // using "_.pluck" callback shorthand
       * _.some(characters, 'blocked');
       * // => true
       *
       * // using "_.where" callback shorthand
       * _.some(characters, { 'age': 1 });
       * // => false
       */
      function some(collection, callback, thisArg) {
        var result;
        callback = lodash.createCallback(callback, thisArg, 3);
  
        var index = -1,
            length = collection ? collection.length : 0;
  
        if (typeof length == 'number') {
          while (++index < length) {
            if ((result = callback(collection[index], index, collection))) {
              break;
            }
          }
        } else {
          forOwn(collection, function(value, index, collection) {
            return !(result = callback(value, index, collection));
          });
        }
        return !!result;
      }
  
      /**
       * Creates an array of elements, sorted in ascending order by the results of
       * running each element in a collection through the callback. This method
       * performs a stable sort, that is, it will preserve the original sort order
       * of equal elements. The callback is bound to `thisArg` and invoked with
       * three arguments; (value, index|key, collection).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an array of property names is provided for `callback` the collection
       * will be sorted by each property value.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Array|Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Array} Returns a new array of sorted elements.
       * @example
       *
       * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); });
       * // => [3, 1, 2]
       *
       * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);
       * // => [3, 1, 2]
       *
       * var characters = [
       *   { 'name': 'barney',  'age': 36 },
       *   { 'name': 'fred',    'age': 40 },
       *   { 'name': 'barney',  'age': 26 },
       *   { 'name': 'fred',    'age': 30 }
       * ];
       *
       * // using "_.pluck" callback shorthand
       * _.map(_.sortBy(characters, 'age'), _.values);
       * // => [['barney', 26], ['fred', 30], ['barney', 36], ['fred', 40]]
       *
       * // sorting by multiple properties
       * _.map(_.sortBy(characters, ['name', 'age']), _.values);
       * // = > [['barney', 26], ['barney', 36], ['fred', 30], ['fred', 40]]
       */
      function sortBy(collection, callback, thisArg) {
        var index = -1,
            isArr = isArray(callback),
            length = collection ? collection.length : 0,
            result = Array(typeof length == 'number' ? length : 0);
  
        if (!isArr) {
          callback = lodash.createCallback(callback, thisArg, 3);
        }
        forEach(collection, function(value, key, collection) {
          var object = result[++index] = getObject();
          if (isArr) {
            object.criteria = map(callback, function(key) { return value[key]; });
          } else {
            (object.criteria = getArray())[0] = callback(value, key, collection);
          }
          object.index = index;
          object.value = value;
        });
  
        length = result.length;
        result.sort(compareAscending);
        while (length--) {
          var object = result[length];
          result[length] = object.value;
          if (!isArr) {
            releaseArray(object.criteria);
          }
          releaseObject(object);
        }
        return result;
      }
  
      /**
       * Converts the `collection` to an array.
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to convert.
       * @returns {Array} Returns the new converted array.
       * @example
       *
       * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
       * // => [2, 3, 4]
       */
      function toArray(collection) {
        if (collection && typeof collection.length == 'number') {
          return slice(collection);
        }
        return values(collection);
      }
  
      /**
       * Performs a deep comparison of each element in a `collection` to the given
       * `properties` object, returning an array of all elements that have equivalent
       * property values.
       *
       * @static
       * @memberOf _
       * @type Function
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Object} props The object of property values to filter by.
       * @returns {Array} Returns a new array of elements that have the given properties.
       * @example
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 36, 'pets': ['hoppy'] },
       *   { 'name': 'fred',   'age': 40, 'pets': ['baby puss', 'dino'] }
       * ];
       *
       * _.where(characters, { 'age': 36 });
       * // => [{ 'name': 'barney', 'age': 36, 'pets': ['hoppy'] }]
       *
       * _.where(characters, { 'pets': ['dino'] });
       * // => [{ 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }]
       */
      var where = filter;
  
      /*--------------------------------------------------------------------------*/
  
      /**
       * Creates an array with all falsey values removed. The values `false`, `null`,
       * `0`, `""`, `undefined`, and `NaN` are all falsey.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {Array} array The array to compact.
       * @returns {Array} Returns a new array of filtered values.
       * @example
       *
       * _.compact([0, 1, false, 2, '', 3]);
       * // => [1, 2, 3]
       */
      function compact(array) {
        var index = -1,
            length = array ? array.length : 0,
            result = [];
  
        while (++index < length) {
          var value = array[index];
          if (value) {
            result.push(value);
          }
        }
        return result;
      }
  
      /**
       * Creates an array excluding all values of the provided arrays using strict
       * equality for comparisons, i.e. `===`.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {Array} array The array to process.
       * @param {...Array} [values] The arrays of values to exclude.
       * @returns {Array} Returns a new array of filtered values.
       * @example
       *
       * _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
       * // => [1, 3, 4]
       */
      function difference(array) {
        return baseDifference(array, baseFlatten(arguments, true, true, 1));
      }
  
      /**
       * This method is like `_.find` except that it returns the index of the first
       * element that passes the callback check, instead of the element itself.
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {Array} array The array to search.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {number} Returns the index of the found element, else `-1`.
       * @example
       *
       * var characters = [
       *   { 'name': 'barney',  'age': 36, 'blocked': false },
       *   { 'name': 'fred',    'age': 40, 'blocked': true },
       *   { 'name': 'pebbles', 'age': 1,  'blocked': false }
       * ];
       *
       * _.findIndex(characters, function(chr) {
       *   return chr.age < 20;
       * });
       * // => 2
       *
       * // using "_.where" callback shorthand
       * _.findIndex(characters, { 'age': 36 });
       * // => 0
       *
       * // using "_.pluck" callback shorthand
       * _.findIndex(characters, 'blocked');
       * // => 1
       */
      function findIndex(array, callback, thisArg) {
        var index = -1,
            length = array ? array.length : 0;
  
        callback = lodash.createCallback(callback, thisArg, 3);
        while (++index < length) {
          if (callback(array[index], index, array)) {
            return index;
          }
        }
        return -1;
      }
  
      /**
       * This method is like `_.findIndex` except that it iterates over elements
       * of a `collection` from right to left.
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {Array} array The array to search.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {number} Returns the index of the found element, else `-1`.
       * @example
       *
       * var characters = [
       *   { 'name': 'barney',  'age': 36, 'blocked': true },
       *   { 'name': 'fred',    'age': 40, 'blocked': false },
       *   { 'name': 'pebbles', 'age': 1,  'blocked': true }
       * ];
       *
       * _.findLastIndex(characters, function(chr) {
       *   return chr.age > 30;
       * });
       * // => 1
       *
       * // using "_.where" callback shorthand
       * _.findLastIndex(characters, { 'age': 36 });
       * // => 0
       *
       * // using "_.pluck" callback shorthand
       * _.findLastIndex(characters, 'blocked');
       * // => 2
       */
      function findLastIndex(array, callback, thisArg) {
        var length = array ? array.length : 0;
        callback = lodash.createCallback(callback, thisArg, 3);
        while (length--) {
          if (callback(array[length], length, array)) {
            return length;
          }
        }
        return -1;
      }
  
      /**
       * Gets the first element or first `n` elements of an array. If a callback
       * is provided elements at the beginning of the array are returned as long
       * as the callback returns truey. The callback is bound to `thisArg` and
       * invoked with three arguments; (value, index, array).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @alias head, take
       * @category Arrays
       * @param {Array} array The array to query.
       * @param {Function|Object|number|string} [callback] The function called
       *  per element or the number of elements to return. If a property name or
       *  object is provided it will be used to create a "_.pluck" or "_.where"
       *  style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {*} Returns the first element(s) of `array`.
       * @example
       *
       * _.first([1, 2, 3]);
       * // => 1
       *
       * _.first([1, 2, 3], 2);
       * // => [1, 2]
       *
       * _.first([1, 2, 3], function(num) {
       *   return num < 3;
       * });
       * // => [1, 2]
       *
       * var characters = [
       *   { 'name': 'barney',  'blocked': true,  'employer': 'slate' },
       *   { 'name': 'fred',    'blocked': false, 'employer': 'slate' },
       *   { 'name': 'pebbles', 'blocked': true,  'employer': 'na' }
       * ];
       *
       * // using "_.pluck" callback shorthand
       * _.first(characters, 'blocked');
       * // => [{ 'name': 'barney', 'blocked': true, 'employer': 'slate' }]
       *
       * // using "_.where" callback shorthand
       * _.pluck(_.first(characters, { 'employer': 'slate' }), 'name');
       * // => ['barney', 'fred']
       */
      function first(array, callback, thisArg) {
        var n = 0,
            length = array ? array.length : 0;
  
        if (typeof callback != 'number' && callback != null) {
          var index = -1;
          callback = lodash.createCallback(callback, thisArg, 3);
          while (++index < length && callback(array[index], index, array)) {
            n++;
          }
        } else {
          n = callback;
          if (n == null || thisArg) {
            return array ? array[0] : undefined;
          }
        }
        return slice(array, 0, nativeMin(nativeMax(0, n), length));
      }
  
      /**
       * Flattens a nested array (the nesting can be to any depth). If `isShallow`
       * is truey, the array will only be flattened a single level. If a callback
       * is provided each element of the array is passed through the callback before
       * flattening. The callback is bound to `thisArg` and invoked with three
       * arguments; (value, index, array).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {Array} array The array to flatten.
       * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Array} Returns a new flattened array.
       * @example
       *
       * _.flatten([1, [2], [3, [[4]]]]);
       * // => [1, 2, 3, 4];
       *
       * _.flatten([1, [2], [3, [[4]]]], true);
       * // => [1, 2, 3, [[4]]];
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 30, 'pets': ['hoppy'] },
       *   { 'name': 'fred',   'age': 40, 'pets': ['baby puss', 'dino'] }
       * ];
       *
       * // using "_.pluck" callback shorthand
       * _.flatten(characters, 'pets');
       * // => ['hoppy', 'baby puss', 'dino']
       */
      function flatten(array, isShallow, callback, thisArg) {
        // juggle arguments
        if (typeof isShallow != 'boolean' && isShallow != null) {
          thisArg = callback;
          callback = (typeof isShallow != 'function' && thisArg && thisArg[isShallow] === array) ? null : isShallow;
          isShallow = false;
        }
        if (callback != null) {
          array = map(array, callback, thisArg);
        }
        return baseFlatten(array, isShallow);
      }
  
      /**
       * Gets the index at which the first occurrence of `value` is found using
       * strict equality for comparisons, i.e. `===`. If the array is already sorted
       * providing `true` for `fromIndex` will run a faster binary search.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {Array} array The array to search.
       * @param {*} value The value to search for.
       * @param {boolean|number} [fromIndex=0] The index to search from or `true`
       *  to perform a binary search on a sorted array.
       * @returns {number} Returns the index of the matched value or `-1`.
       * @example
       *
       * _.indexOf([1, 2, 3, 1, 2, 3], 2);
       * // => 1
       *
       * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3);
       * // => 4
       *
       * _.indexOf([1, 1, 2, 2, 3, 3], 2, true);
       * // => 2
       */
      function indexOf(array, value, fromIndex) {
        if (typeof fromIndex == 'number') {
          var length = array ? array.length : 0;
          fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0);
        } else if (fromIndex) {
          var index = sortedIndex(array, value);
          return array[index] === value ? index : -1;
        }
        return baseIndexOf(array, value, fromIndex);
      }
  
      /**
       * Gets all but the last element or last `n` elements of an array. If a
       * callback is provided elements at the end of the array are excluded from
       * the result as long as the callback returns truey. The callback is bound
       * to `thisArg` and invoked with three arguments; (value, index, array).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {Array} array The array to query.
       * @param {Function|Object|number|string} [callback=1] The function called
       *  per element or the number of elements to exclude. If a property name or
       *  object is provided it will be used to create a "_.pluck" or "_.where"
       *  style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Array} Returns a slice of `array`.
       * @example
       *
       * _.initial([1, 2, 3]);
       * // => [1, 2]
       *
       * _.initial([1, 2, 3], 2);
       * // => [1]
       *
       * _.initial([1, 2, 3], function(num) {
       *   return num > 1;
       * });
       * // => [1]
       *
       * var characters = [
       *   { 'name': 'barney',  'blocked': false, 'employer': 'slate' },
       *   { 'name': 'fred',    'blocked': true,  'employer': 'slate' },
       *   { 'name': 'pebbles', 'blocked': true,  'employer': 'na' }
       * ];
       *
       * // using "_.pluck" callback shorthand
       * _.initial(characters, 'blocked');
       * // => [{ 'name': 'barney',  'blocked': false, 'employer': 'slate' }]
       *
       * // using "_.where" callback shorthand
       * _.pluck(_.initial(characters, { 'employer': 'na' }), 'name');
       * // => ['barney', 'fred']
       */
      function initial(array, callback, thisArg) {
        var n = 0,
            length = array ? array.length : 0;
  
        if (typeof callback != 'number' && callback != null) {
          var index = length;
          callback = lodash.createCallback(callback, thisArg, 3);
          while (index-- && callback(array[index], index, array)) {
            n++;
          }
        } else {
          n = (callback == null || thisArg) ? 1 : callback || n;
        }
        return slice(array, 0, nativeMin(nativeMax(0, length - n), length));
      }
  
      /**
       * Creates an array of unique values present in all provided arrays using
       * strict equality for comparisons, i.e. `===`.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {...Array} [array] The arrays to inspect.
       * @returns {Array} Returns an array of shared values.
       * @example
       *
       * _.intersection([1, 2, 3], [5, 2, 1, 4], [2, 1]);
       * // => [1, 2]
       */
      function intersection() {
        var args = [],
            argsIndex = -1,
            argsLength = arguments.length,
            caches = getArray(),
            indexOf = getIndexOf(),
            trustIndexOf = indexOf === baseIndexOf,
            seen = getArray();
  
        while (++argsIndex < argsLength) {
          var value = arguments[argsIndex];
          if (isArray(value) || isArguments(value)) {
            args.push(value);
            caches.push(trustIndexOf && value.length >= largeArraySize &&
              createCache(argsIndex ? args[argsIndex] : seen));
          }
        }
        var array = args[0],
            index = -1,
            length = array ? array.length : 0,
            result = [];
  
        outer:
        while (++index < length) {
          var cache = caches[0];
          value = array[index];
  
          if ((cache ? cacheIndexOf(cache, value) : indexOf(seen, value)) < 0) {
            argsIndex = argsLength;
            (cache || seen).push(value);
            while (--argsIndex) {
              cache = caches[argsIndex];
              if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value)) < 0) {
                continue outer;
              }
            }
            result.push(value);
          }
        }
        while (argsLength--) {
          cache = caches[argsLength];
          if (cache) {
            releaseObject(cache);
          }
        }
        releaseArray(caches);
        releaseArray(seen);
        return result;
      }
  
      /**
       * Gets the last element or last `n` elements of an array. If a callback is
       * provided elements at the end of the array are returned as long as the
       * callback returns truey. The callback is bound to `thisArg` and invoked
       * with three arguments; (value, index, array).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {Array} array The array to query.
       * @param {Function|Object|number|string} [callback] The function called
       *  per element or the number of elements to return. If a property name or
       *  object is provided it will be used to create a "_.pluck" or "_.where"
       *  style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {*} Returns the last element(s) of `array`.
       * @example
       *
       * _.last([1, 2, 3]);
       * // => 3
       *
       * _.last([1, 2, 3], 2);
       * // => [2, 3]
       *
       * _.last([1, 2, 3], function(num) {
       *   return num > 1;
       * });
       * // => [2, 3]
       *
       * var characters = [
       *   { 'name': 'barney',  'blocked': false, 'employer': 'slate' },
       *   { 'name': 'fred',    'blocked': true,  'employer': 'slate' },
       *   { 'name': 'pebbles', 'blocked': true,  'employer': 'na' }
       * ];
       *
       * // using "_.pluck" callback shorthand
       * _.pluck(_.last(characters, 'blocked'), 'name');
       * // => ['fred', 'pebbles']
       *
       * // using "_.where" callback shorthand
       * _.last(characters, { 'employer': 'na' });
       * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }]
       */
      function last(array, callback, thisArg) {
        var n = 0,
            length = array ? array.length : 0;
  
        if (typeof callback != 'number' && callback != null) {
          var index = length;
          callback = lodash.createCallback(callback, thisArg, 3);
          while (index-- && callback(array[index], index, array)) {
            n++;
          }
        } else {
          n = callback;
          if (n == null || thisArg) {
            return array ? array[length - 1] : undefined;
          }
        }
        return slice(array, nativeMax(0, length - n));
      }
  
      /**
       * Gets the index at which the last occurrence of `value` is found using strict
       * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
       * as the offset from the end of the collection.
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {Array} array The array to search.
       * @param {*} value The value to search for.
       * @param {number} [fromIndex=array.length-1] The index to search from.
       * @returns {number} Returns the index of the matched value or `-1`.
       * @example
       *
       * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
       * // => 4
       *
       * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
       * // => 1
       */
      function lastIndexOf(array, value, fromIndex) {
        var index = array ? array.length : 0;
        if (typeof fromIndex == 'number') {
          index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1;
        }
        while (index--) {
          if (array[index] === value) {
            return index;
          }
        }
        return -1;
      }
  
      /**
       * Removes all provided values from the given array using strict equality for
       * comparisons, i.e. `===`.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {Array} array The array to modify.
       * @param {...*} [value] The values to remove.
       * @returns {Array} Returns `array`.
       * @example
       *
       * var array = [1, 2, 3, 1, 2, 3];
       * _.pull(array, 2, 3);
       * console.log(array);
       * // => [1, 1]
       */
      function pull(array) {
        var args = arguments,
            argsIndex = 0,
            argsLength = args.length,
            length = array ? array.length : 0;
  
        while (++argsIndex < argsLength) {
          var index = -1,
              value = args[argsIndex];
          while (++index < length) {
            if (array[index] === value) {
              splice.call(array, index--, 1);
              length--;
            }
          }
        }
        return array;
      }
  
      /**
       * Creates an array of numbers (positive and/or negative) progressing from
       * `start` up to but not including `end`. If `start` is less than `stop` a
       * zero-length range is created unless a negative `step` is specified.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {number} [start=0] The start of the range.
       * @param {number} end The end of the range.
       * @param {number} [step=1] The value to increment or decrement by.
       * @returns {Array} Returns a new range array.
       * @example
       *
       * _.range(4);
       * // => [0, 1, 2, 3]
       *
       * _.range(1, 5);
       * // => [1, 2, 3, 4]
       *
       * _.range(0, 20, 5);
       * // => [0, 5, 10, 15]
       *
       * _.range(0, -4, -1);
       * // => [0, -1, -2, -3]
       *
       * _.range(1, 4, 0);
       * // => [1, 1, 1]
       *
       * _.range(0);
       * // => []
       */
      function range(start, end, step) {
        start = +start || 0;
        step = typeof step == 'number' ? step : (+step || 1);
  
        if (end == null) {
          end = start;
          start = 0;
        }
        // use `Array(length)` so engines like Chakra and V8 avoid slower modes
        // http://youtu.be/XAqIpGU8ZZk#t=17m25s
        var index = -1,
            length = nativeMax(0, ceil((end - start) / (step || 1))),
            result = Array(length);
  
        while (++index < length) {
          result[index] = start;
          start += step;
        }
        return result;
      }
  
      /**
       * Removes all elements from an array that the callback returns truey for
       * and returns an array of removed elements. The callback is bound to `thisArg`
       * and invoked with three arguments; (value, index, array).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {Array} array The array to modify.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Array} Returns a new array of removed elements.
       * @example
       *
       * var array = [1, 2, 3, 4, 5, 6];
       * var evens = _.remove(array, function(num) { return num % 2 == 0; });
       *
       * console.log(array);
       * // => [1, 3, 5]
       *
       * console.log(evens);
       * // => [2, 4, 6]
       */
      function remove(array, callback, thisArg) {
        var index = -1,
            length = array ? array.length : 0,
            result = [];
  
        callback = lodash.createCallback(callback, thisArg, 3);
        while (++index < length) {
          var value = array[index];
          if (callback(value, index, array)) {
            result.push(value);
            splice.call(array, index--, 1);
            length--;
          }
        }
        return result;
      }
  
      /**
       * The opposite of `_.initial` this method gets all but the first element or
       * first `n` elements of an array. If a callback function is provided elements
       * at the beginning of the array are excluded from the result as long as the
       * callback returns truey. The callback is bound to `thisArg` and invoked
       * with three arguments; (value, index, array).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @alias drop, tail
       * @category Arrays
       * @param {Array} array The array to query.
       * @param {Function|Object|number|string} [callback=1] The function called
       *  per element or the number of elements to exclude. If a property name or
       *  object is provided it will be used to create a "_.pluck" or "_.where"
       *  style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Array} Returns a slice of `array`.
       * @example
       *
       * _.rest([1, 2, 3]);
       * // => [2, 3]
       *
       * _.rest([1, 2, 3], 2);
       * // => [3]
       *
       * _.rest([1, 2, 3], function(num) {
       *   return num < 3;
       * });
       * // => [3]
       *
       * var characters = [
       *   { 'name': 'barney',  'blocked': true,  'employer': 'slate' },
       *   { 'name': 'fred',    'blocked': false,  'employer': 'slate' },
       *   { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
       * ];
       *
       * // using "_.pluck" callback shorthand
       * _.pluck(_.rest(characters, 'blocked'), 'name');
       * // => ['fred', 'pebbles']
       *
       * // using "_.where" callback shorthand
       * _.rest(characters, { 'employer': 'slate' });
       * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }]
       */
      function rest(array, callback, thisArg) {
        if (typeof callback != 'number' && callback != null) {
          var n = 0,
              index = -1,
              length = array ? array.length : 0;
  
          callback = lodash.createCallback(callback, thisArg, 3);
          while (++index < length && callback(array[index], index, array)) {
            n++;
          }
        } else {
          n = (callback == null || thisArg) ? 1 : nativeMax(0, callback);
        }
        return slice(array, n);
      }
  
      /**
       * Uses a binary search to determine the smallest index at which a value
       * should be inserted into a given sorted array in order to maintain the sort
       * order of the array. If a callback is provided it will be executed for
       * `value` and each element of `array` to compute their sort ranking. The
       * callback is bound to `thisArg` and invoked with one argument; (value).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {Array} array The array to inspect.
       * @param {*} value The value to evaluate.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {number} Returns the index at which `value` should be inserted
       *  into `array`.
       * @example
       *
       * _.sortedIndex([20, 30, 50], 40);
       * // => 2
       *
       * // using "_.pluck" callback shorthand
       * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
       * // => 2
       *
       * var dict = {
       *   'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 }
       * };
       *
       * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
       *   return dict.wordToNumber[word];
       * });
       * // => 2
       *
       * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
       *   return this.wordToNumber[word];
       * }, dict);
       * // => 2
       */
      function sortedIndex(array, value, callback, thisArg) {
        var low = 0,
            high = array ? array.length : low;
  
        // explicitly reference `identity` for better inlining in Firefox
        callback = callback ? lodash.createCallback(callback, thisArg, 1) : identity;
        value = callback(value);
  
        while (low < high) {
          var mid = (low + high) >>> 1;
          (callback(array[mid]) < value)
            ? low = mid + 1
            : high = mid;
        }
        return low;
      }
  
      /**
       * Creates an array of unique values, in order, of the provided arrays using
       * strict equality for comparisons, i.e. `===`.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {...Array} [array] The arrays to inspect.
       * @returns {Array} Returns an array of combined values.
       * @example
       *
       * _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]);
       * // => [1, 2, 3, 5, 4]
       */
      function union() {
        return baseUniq(baseFlatten(arguments, true, true));
      }
  
      /**
       * Creates a duplicate-value-free version of an array using strict equality
       * for comparisons, i.e. `===`. If the array is sorted, providing
       * `true` for `isSorted` will use a faster algorithm. If a callback is provided
       * each element of `array` is passed through the callback before uniqueness
       * is computed. The callback is bound to `thisArg` and invoked with three
       * arguments; (value, index, array).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @alias unique
       * @category Arrays
       * @param {Array} array The array to process.
       * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Array} Returns a duplicate-value-free array.
       * @example
       *
       * _.uniq([1, 2, 1, 3, 1]);
       * // => [1, 2, 3]
       *
       * _.uniq([1, 1, 2, 2, 3], true);
       * // => [1, 2, 3]
       *
       * _.uniq(['A', 'b', 'C', 'a', 'B', 'c'], function(letter) { return letter.toLowerCase(); });
       * // => ['A', 'b', 'C']
       *
       * _.uniq([1, 2.5, 3, 1.5, 2, 3.5], function(num) { return this.floor(num); }, Math);
       * // => [1, 2.5, 3]
       *
       * // using "_.pluck" callback shorthand
       * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
       * // => [{ 'x': 1 }, { 'x': 2 }]
       */
      function uniq(array, isSorted, callback, thisArg) {
        // juggle arguments
        if (typeof isSorted != 'boolean' && isSorted != null) {
          thisArg = callback;
          callback = (typeof isSorted != 'function' && thisArg && thisArg[isSorted] === array) ? null : isSorted;
          isSorted = false;
        }
        if (callback != null) {
          callback = lodash.createCallback(callback, thisArg, 3);
        }
        return baseUniq(array, isSorted, callback);
      }
  
      /**
       * Creates an array excluding all provided values using strict equality for
       * comparisons, i.e. `===`.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {Array} array The array to filter.
       * @param {...*} [value] The values to exclude.
       * @returns {Array} Returns a new array of filtered values.
       * @example
       *
       * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
       * // => [2, 3, 4]
       */
      function without(array) {
        return baseDifference(array, slice(arguments, 1));
      }
  
      /**
       * Creates an array that is the symmetric difference of the provided arrays.
       * See http://en.wikipedia.org/wiki/Symmetric_difference.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {...Array} [array] The arrays to inspect.
       * @returns {Array} Returns an array of values.
       * @example
       *
       * _.xor([1, 2, 3], [5, 2, 1, 4]);
       * // => [3, 5, 4]
       *
       * _.xor([1, 2, 5], [2, 3, 5], [3, 4, 5]);
       * // => [1, 4, 5]
       */
      function xor() {
        var index = -1,
            length = arguments.length;
  
        while (++index < length) {
          var array = arguments[index];
          if (isArray(array) || isArguments(array)) {
            var result = result
              ? baseUniq(baseDifference(result, array).concat(baseDifference(array, result)))
              : array;
          }
        }
        return result || [];
      }
  
      /**
       * Creates an array of grouped elements, the first of which contains the first
       * elements of the given arrays, the second of which contains the second
       * elements of the given arrays, and so on.
       *
       * @static
       * @memberOf _
       * @alias unzip
       * @category Arrays
       * @param {...Array} [array] Arrays to process.
       * @returns {Array} Returns a new array of grouped elements.
       * @example
       *
       * _.zip(['fred', 'barney'], [30, 40], [true, false]);
       * // => [['fred', 30, true], ['barney', 40, false]]
       */
      function zip() {
        var array = arguments.length > 1 ? arguments : arguments[0],
            index = -1,
            length = array ? max(pluck(array, 'length')) : 0,
            result = Array(length < 0 ? 0 : length);
  
        while (++index < length) {
          result[index] = pluck(array, index);
        }
        return result;
      }
  
      /**
       * Creates an object composed from arrays of `keys` and `values`. Provide
       * either a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`
       * or two arrays, one of `keys` and one of corresponding `values`.
       *
       * @static
       * @memberOf _
       * @alias object
       * @category Arrays
       * @param {Array} keys The array of keys.
       * @param {Array} [values=[]] The array of values.
       * @returns {Object} Returns an object composed of the given keys and
       *  corresponding values.
       * @example
       *
       * _.zipObject(['fred', 'barney'], [30, 40]);
       * // => { 'fred': 30, 'barney': 40 }
       */
      function zipObject(keys, values) {
        var index = -1,
            length = keys ? keys.length : 0,
            result = {};
  
        if (!values && length && !isArray(keys[0])) {
          values = [];
        }
        while (++index < length) {
          var key = keys[index];
          if (values) {
            result[key] = values[index];
          } else if (key) {
            result[key[0]] = key[1];
          }
        }
        return result;
      }
  
      /*--------------------------------------------------------------------------*/
  
      /**
       * Creates a function that executes `func`, with  the `this` binding and
       * arguments of the created function, only after being called `n` times.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {number} n The number of times the function must be called before
       *  `func` is executed.
       * @param {Function} func The function to restrict.
       * @returns {Function} Returns the new restricted function.
       * @example
       *
       * var saves = ['profile', 'settings'];
       *
       * var done = _.after(saves.length, function() {
       *   console.log('Done saving!');
       * });
       *
       * _.forEach(saves, function(type) {
       *   asyncSave({ 'type': type, 'complete': done });
       * });
       * // => logs 'Done saving!', after all saves have completed
       */
      function after(n, func) {
        if (!isFunction(func)) {
          throw new TypeError;
        }
        return function() {
          if (--n < 1) {
            return func.apply(this, arguments);
          }
        };
      }
  
      /**
       * Creates a function that, when called, invokes `func` with the `this`
       * binding of `thisArg` and prepends any additional `bind` arguments to those
       * provided to the bound function.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {Function} func The function to bind.
       * @param {*} [thisArg] The `this` binding of `func`.
       * @param {...*} [arg] Arguments to be partially applied.
       * @returns {Function} Returns the new bound function.
       * @example
       *
       * var func = function(greeting) {
       *   return greeting + ' ' + this.name;
       * };
       *
       * func = _.bind(func, { 'name': 'fred' }, 'hi');
       * func();
       * // => 'hi fred'
       */
      function bind(func, thisArg) {
        return arguments.length > 2
          ? createWrapper(func, 17, slice(arguments, 2), null, thisArg)
          : createWrapper(func, 1, null, null, thisArg);
      }
  
      /**
       * Binds methods of an object to the object itself, overwriting the existing
       * method. Method names may be specified as individual arguments or as arrays
       * of method names. If no method names are provided all the function properties
       * of `object` will be bound.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {Object} object The object to bind and assign the bound methods to.
       * @param {...string} [methodName] The object method names to
       *  bind, specified as individual method names or arrays of method names.
       * @returns {Object} Returns `object`.
       * @example
       *
       * var view = {
       *   'label': 'docs',
       *   'onClick': function() { console.log('clicked ' + this.label); }
       * };
       *
       * _.bindAll(view);
       * jQuery('#docs').on('click', view.onClick);
       * // => logs 'clicked docs', when the button is clicked
       */
      function bindAll(object) {
        var funcs = arguments.length > 1 ? baseFlatten(arguments, true, false, 1) : functions(object),
            index = -1,
            length = funcs.length;
  
        while (++index < length) {
          var key = funcs[index];
          object[key] = createWrapper(object[key], 1, null, null, object);
        }
        return object;
      }
  
      /**
       * Creates a function that, when called, invokes the method at `object[key]`
       * and prepends any additional `bindKey` arguments to those provided to the bound
       * function. This method differs from `_.bind` by allowing bound functions to
       * reference methods that will be redefined or don't yet exist.
       * See http://michaux.ca/articles/lazy-function-definition-pattern.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {Object} object The object the method belongs to.
       * @param {string} key The key of the method.
       * @param {...*} [arg] Arguments to be partially applied.
       * @returns {Function} Returns the new bound function.
       * @example
       *
       * var object = {
       *   'name': 'fred',
       *   'greet': function(greeting) {
       *     return greeting + ' ' + this.name;
       *   }
       * };
       *
       * var func = _.bindKey(object, 'greet', 'hi');
       * func();
       * // => 'hi fred'
       *
       * object.greet = function(greeting) {
       *   return greeting + 'ya ' + this.name + '!';
       * };
       *
       * func();
       * // => 'hiya fred!'
       */
      function bindKey(object, key) {
        return arguments.length > 2
          ? createWrapper(key, 19, slice(arguments, 2), null, object)
          : createWrapper(key, 3, null, null, object);
      }
  
      /**
       * Creates a function that is the composition of the provided functions,
       * where each function consumes the return value of the function that follows.
       * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
       * Each function is executed with the `this` binding of the composed function.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {...Function} [func] Functions to compose.
       * @returns {Function} Returns the new composed function.
       * @example
       *
       * var realNameMap = {
       *   'pebbles': 'penelope'
       * };
       *
       * var format = function(name) {
       *   name = realNameMap[name.toLowerCase()] || name;
       *   return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase();
       * };
       *
       * var greet = function(formatted) {
       *   return 'Hiya ' + formatted + '!';
       * };
       *
       * var welcome = _.compose(greet, format);
       * welcome('pebbles');
       * // => 'Hiya Penelope!'
       */
      function compose() {
        var funcs = arguments,
            length = funcs.length;
  
        while (length--) {
          if (!isFunction(funcs[length])) {
            throw new TypeError;
          }
        }
        return function() {
          var args = arguments,
              length = funcs.length;
  
          while (length--) {
            args = [funcs[length].apply(this, args)];
          }
          return args[0];
        };
      }
  
      /**
       * Creates a function which accepts one or more arguments of `func` that when
       * invoked either executes `func` returning its result, if all `func` arguments
       * have been provided, or returns a function that accepts one or more of the
       * remaining `func` arguments, and so on. The arity of `func` can be specified
       * if `func.length` is not sufficient.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {Function} func The function to curry.
       * @param {number} [arity=func.length] The arity of `func`.
       * @returns {Function} Returns the new curried function.
       * @example
       *
       * var curried = _.curry(function(a, b, c) {
       *   console.log(a + b + c);
       * });
       *
       * curried(1)(2)(3);
       * // => 6
       *
       * curried(1, 2)(3);
       * // => 6
       *
       * curried(1, 2, 3);
       * // => 6
       */
      function curry(func, arity) {
        arity = typeof arity == 'number' ? arity : (+arity || func.length);
        return createWrapper(func, 4, null, null, null, arity);
      }
  
      /**
       * Creates a function that will delay the execution of `func` until after
       * `wait` milliseconds have elapsed since the last time it was invoked.
       * Provide an options object to indicate that `func` should be invoked on
       * the leading and/or trailing edge of the `wait` timeout. Subsequent calls
       * to the debounced function will return the result of the last `func` call.
       *
       * Note: If `leading` and `trailing` options are `true` `func` will be called
       * on the trailing edge of the timeout only if the the debounced function is
       * invoked more than once during the `wait` timeout.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {Function} func The function to debounce.
       * @param {number} wait The number of milliseconds to delay.
       * @param {Object} [options] The options object.
       * @param {boolean} [options.leading=false] Specify execution on the leading edge of the timeout.
       * @param {number} [options.maxWait] The maximum time `func` is allowed to be delayed before it's called.
       * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
       * @returns {Function} Returns the new debounced function.
       * @example
       *
       * // avoid costly calculations while the window size is in flux
       * var lazyLayout = _.debounce(calculateLayout, 150);
       * jQuery(window).on('resize', lazyLayout);
       *
       * // execute `sendMail` when the click event is fired, debouncing subsequent calls
       * jQuery('#postbox').on('click', _.debounce(sendMail, 300, {
       *   'leading': true,
       *   'trailing': false
       * });
       *
       * // ensure `batchLog` is executed once after 1 second of debounced calls
       * var source = new EventSource('/stream');
       * source.addEventListener('message', _.debounce(batchLog, 250, {
       *   'maxWait': 1000
       * }, false);
       */
      function debounce(func, wait, options) {
        var args,
            maxTimeoutId,
            result,
            stamp,
            thisArg,
            timeoutId,
            trailingCall,
            lastCalled = 0,
            maxWait = false,
            trailing = true;
  
        if (!isFunction(func)) {
          throw new TypeError;
        }
        wait = nativeMax(0, wait) || 0;
        if (options === true) {
          var leading = true;
          trailing = false;
        } else if (isObject(options)) {
          leading = options.leading;
          maxWait = 'maxWait' in options && (nativeMax(wait, options.maxWait) || 0);
          trailing = 'trailing' in options ? options.trailing : trailing;
        }
        var delayed = function() {
          var remaining = wait - (now() - stamp);
          if (remaining <= 0) {
            if (maxTimeoutId) {
              clearTimeout(maxTimeoutId);
            }
            var isCalled = trailingCall;
            maxTimeoutId = timeoutId = trailingCall = undefined;
            if (isCalled) {
              lastCalled = now();
              result = func.apply(thisArg, args);
              if (!timeoutId && !maxTimeoutId) {
                args = thisArg = null;
              }
            }
          } else {
            timeoutId = setTimeout(delayed, remaining);
          }
        };
  
        var maxDelayed = function() {
          if (timeoutId) {
            clearTimeout(timeoutId);
          }
          maxTimeoutId = timeoutId = trailingCall = undefined;
          if (trailing || (maxWait !== wait)) {
            lastCalled = now();
            result = func.apply(thisArg, args);
            if (!timeoutId && !maxTimeoutId) {
              args = thisArg = null;
            }
          }
        };
  
        return function() {
          args = arguments;
          stamp = now();
          thisArg = this;
          trailingCall = trailing && (timeoutId || !leading);
  
          if (maxWait === false) {
            var leadingCall = leading && !timeoutId;
          } else {
            if (!maxTimeoutId && !leading) {
              lastCalled = stamp;
            }
            var remaining = maxWait - (stamp - lastCalled),
                isCalled = remaining <= 0;
  
            if (isCalled) {
              if (maxTimeoutId) {
                maxTimeoutId = clearTimeout(maxTimeoutId);
              }
              lastCalled = stamp;
              result = func.apply(thisArg, args);
            }
            else if (!maxTimeoutId) {
              maxTimeoutId = setTimeout(maxDelayed, remaining);
            }
          }
          if (isCalled && timeoutId) {
            timeoutId = clearTimeout(timeoutId);
          }
          else if (!timeoutId && wait !== maxWait) {
            timeoutId = setTimeout(delayed, wait);
          }
          if (leadingCall) {
            isCalled = true;
            result = func.apply(thisArg, args);
          }
          if (isCalled && !timeoutId && !maxTimeoutId) {
            args = thisArg = null;
          }
          return result;
        };
      }
  
      /**
       * Defers executing the `func` function until the current call stack has cleared.
       * Additional arguments will be provided to `func` when it is invoked.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {Function} func The function to defer.
       * @param {...*} [arg] Arguments to invoke the function with.
       * @returns {number} Returns the timer id.
       * @example
       *
       * _.defer(function(text) { console.log(text); }, 'deferred');
       * // logs 'deferred' after one or more milliseconds
       */
      function defer(func) {
        if (!isFunction(func)) {
          throw new TypeError;
        }
        var args = slice(arguments, 1);
        return setTimeout(function() { func.apply(undefined, args); }, 1);
      }
  
      /**
       * Executes the `func` function after `wait` milliseconds. Additional arguments
       * will be provided to `func` when it is invoked.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {Function} func The function to delay.
       * @param {number} wait The number of milliseconds to delay execution.
       * @param {...*} [arg] Arguments to invoke the function with.
       * @returns {number} Returns the timer id.
       * @example
       *
       * _.delay(function(text) { console.log(text); }, 1000, 'later');
       * // => logs 'later' after one second
       */
      function delay(func, wait) {
        if (!isFunction(func)) {
          throw new TypeError;
        }
        var args = slice(arguments, 2);
        return setTimeout(function() { func.apply(undefined, args); }, wait);
      }
  
      /**
       * Creates a function that memoizes the result of `func`. If `resolver` is
       * provided it will be used to determine the cache key for storing the result
       * based on the arguments provided to the memoized function. By default, the
       * first argument provided to the memoized function is used as the cache key.
       * The `func` is executed with the `this` binding of the memoized function.
       * The result cache is exposed as the `cache` property on the memoized function.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {Function} func The function to have its output memoized.
       * @param {Function} [resolver] A function used to resolve the cache key.
       * @returns {Function} Returns the new memoizing function.
       * @example
       *
       * var fibonacci = _.memoize(function(n) {
       *   return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
       * });
       *
       * fibonacci(9)
       * // => 34
       *
       * var data = {
       *   'fred': { 'name': 'fred', 'age': 40 },
       *   'pebbles': { 'name': 'pebbles', 'age': 1 }
       * };
       *
       * // modifying the result cache
       * var get = _.memoize(function(name) { return data[name]; }, _.identity);
       * get('pebbles');
       * // => { 'name': 'pebbles', 'age': 1 }
       *
       * get.cache.pebbles.name = 'penelope';
       * get('pebbles');
       * // => { 'name': 'penelope', 'age': 1 }
       */
      function memoize(func, resolver) {
        if (!isFunction(func)) {
          throw new TypeError;
        }
        var memoized = function() {
          var cache = memoized.cache,
              key = resolver ? resolver.apply(this, arguments) : keyPrefix + arguments[0];
  
          return hasOwnProperty.call(cache, key)
            ? cache[key]
            : (cache[key] = func.apply(this, arguments));
        }
        memoized.cache = {};
        return memoized;
      }
  
      /**
       * Creates a function that is restricted to execute `func` once. Repeat calls to
       * the function will return the value of the first call. The `func` is executed
       * with the `this` binding of the created function.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {Function} func The function to restrict.
       * @returns {Function} Returns the new restricted function.
       * @example
       *
       * var initialize = _.once(createApplication);
       * initialize();
       * initialize();
       * // `initialize` executes `createApplication` once
       */
      function once(func) {
        var ran,
            result;
  
        if (!isFunction(func)) {
          throw new TypeError;
        }
        return function() {
          if (ran) {
            return result;
          }
          ran = true;
          result = func.apply(this, arguments);
  
          // clear the `func` variable so the function may be garbage collected
          func = null;
          return result;
        };
      }
  
      /**
       * Creates a function that, when called, invokes `func` with any additional
       * `partial` arguments prepended to those provided to the new function. This
       * method is similar to `_.bind` except it does **not** alter the `this` binding.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {Function} func The function to partially apply arguments to.
       * @param {...*} [arg] Arguments to be partially applied.
       * @returns {Function} Returns the new partially applied function.
       * @example
       *
       * var greet = function(greeting, name) { return greeting + ' ' + name; };
       * var hi = _.partial(greet, 'hi');
       * hi('fred');
       * // => 'hi fred'
       */
      function partial(func) {
        return createWrapper(func, 16, slice(arguments, 1));
      }
  
      /**
       * This method is like `_.partial` except that `partial` arguments are
       * appended to those provided to the new function.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {Function} func The function to partially apply arguments to.
       * @param {...*} [arg] Arguments to be partially applied.
       * @returns {Function} Returns the new partially applied function.
       * @example
       *
       * var defaultsDeep = _.partialRight(_.merge, _.defaults);
       *
       * var options = {
       *   'variable': 'data',
       *   'imports': { 'jq': $ }
       * };
       *
       * defaultsDeep(options, _.templateSettings);
       *
       * options.variable
       * // => 'data'
       *
       * options.imports
       * // => { '_': _, 'jq': $ }
       */
      function partialRight(func) {
        return createWrapper(func, 32, null, slice(arguments, 1));
      }
  
      /**
       * Creates a function that, when executed, will only call the `func` function
       * at most once per every `wait` milliseconds. Provide an options object to
       * indicate that `func` should be invoked on the leading and/or trailing edge
       * of the `wait` timeout. Subsequent calls to the throttled function will
       * return the result of the last `func` call.
       *
       * Note: If `leading` and `trailing` options are `true` `func` will be called
       * on the trailing edge of the timeout only if the the throttled function is
       * invoked more than once during the `wait` timeout.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {Function} func The function to throttle.
       * @param {number} wait The number of milliseconds to throttle executions to.
       * @param {Object} [options] The options object.
       * @param {boolean} [options.leading=true] Specify execution on the leading edge of the timeout.
       * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
       * @returns {Function} Returns the new throttled function.
       * @example
       *
       * // avoid excessively updating the position while scrolling
       * var throttled = _.throttle(updatePosition, 100);
       * jQuery(window).on('scroll', throttled);
       *
       * // execute `renewToken` when the click event is fired, but not more than once every 5 minutes
       * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, {
       *   'trailing': false
       * }));
       */
      function throttle(func, wait, options) {
        var leading = true,
            trailing = true;
  
        if (!isFunction(func)) {
          throw new TypeError;
        }
        if (options === false) {
          leading = false;
        } else if (isObject(options)) {
          leading = 'leading' in options ? options.leading : leading;
          trailing = 'trailing' in options ? options.trailing : trailing;
        }
        debounceOptions.leading = leading;
        debounceOptions.maxWait = wait;
        debounceOptions.trailing = trailing;
  
        return debounce(func, wait, debounceOptions);
      }
  
      /**
       * Creates a function that provides `value` to the wrapper function as its
       * first argument. Additional arguments provided to the function are appended
       * to those provided to the wrapper function. The wrapper is executed with
       * the `this` binding of the created function.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {*} value The value to wrap.
       * @param {Function} wrapper The wrapper function.
       * @returns {Function} Returns the new function.
       * @example
       *
       * var p = _.wrap(_.escape, function(func, text) {
       *   return '<p>' + func(text) + '</p>';
       * });
       *
       * p('Fred, Wilma, & Pebbles');
       * // => '<p>Fred, Wilma, &amp; Pebbles</p>'
       */
      function wrap(value, wrapper) {
        return createWrapper(wrapper, 16, [value]);
      }
  
      /*--------------------------------------------------------------------------*/
  
      /**
       * Creates a function that returns `value`.
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @param {*} value The value to return from the new function.
       * @returns {Function} Returns the new function.
       * @example
       *
       * var object = { 'name': 'fred' };
       * var getter = _.constant(object);
       * getter() === object;
       * // => true
       */
      function constant(value) {
        return function() {
          return value;
        };
      }
  
      /**
       * Produces a callback bound to an optional `thisArg`. If `func` is a property
       * name the created callback will return the property value for a given element.
       * If `func` is an object the created callback will return `true` for elements
       * that contain the equivalent object properties, otherwise it will return `false`.
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @param {*} [func=identity] The value to convert to a callback.
       * @param {*} [thisArg] The `this` binding of the created callback.
       * @param {number} [argCount] The number of arguments the callback accepts.
       * @returns {Function} Returns a callback function.
       * @example
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 36 },
       *   { 'name': 'fred',   'age': 40 }
       * ];
       *
       * // wrap to create custom callback shorthands
       * _.createCallback = _.wrap(_.createCallback, function(func, callback, thisArg) {
       *   var match = /^(.+?)__([gl]t)(.+)$/.exec(callback);
       *   return !match ? func(callback, thisArg) : function(object) {
       *     return match[2] == 'gt' ? object[match[1]] > match[3] : object[match[1]] < match[3];
       *   };
       * });
       *
       * _.filter(characters, 'age__gt38');
       * // => [{ 'name': 'fred', 'age': 40 }]
       */
      function createCallback(func, thisArg, argCount) {
        var type = typeof func;
        if (func == null || type == 'function') {
          return baseCreateCallback(func, thisArg, argCount);
        }
        // handle "_.pluck" style callback shorthands
        if (type != 'object') {
          return property(func);
        }
        var props = keys(func),
            key = props[0],
            a = func[key];
  
        // handle "_.where" style callback shorthands
        if (props.length == 1 && a === a && !isObject(a)) {
          // fast path the common case of providing an object with a single
          // property containing a primitive value
          return function(object) {
            var b = object[key];
            return a === b && (a !== 0 || (1 / a == 1 / b));
          };
        }
        return function(object) {
          var length = props.length,
              result = false;
  
          while (length--) {
            if (!(result = baseIsEqual(object[props[length]], func[props[length]], null, true))) {
              break;
            }
          }
          return result;
        };
      }
  
      /**
       * Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their
       * corresponding HTML entities.
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @param {string} string The string to escape.
       * @returns {string} Returns the escaped string.
       * @example
       *
       * _.escape('Fred, Wilma, & Pebbles');
       * // => 'Fred, Wilma, &amp; Pebbles'
       */
      function escape(string) {
        return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar);
      }
  
      /**
       * This method returns the first argument provided to it.
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @param {*} value Any value.
       * @returns {*} Returns `value`.
       * @example
       *
       * var object = { 'name': 'fred' };
       * _.identity(object) === object;
       * // => true
       */
      function identity(value) {
        return value;
      }
  
      /**
       * Adds function properties of a source object to the destination object.
       * If `object` is a function methods will be added to its prototype as well.
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @param {Function|Object} [object=lodash] object The destination object.
       * @param {Object} source The object of functions to add.
       * @param {Object} [options] The options object.
       * @param {boolean} [options.chain=true] Specify whether the functions added are chainable.
       * @example
       *
       * function capitalize(string) {
       *   return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
       * }
       *
       * _.mixin({ 'capitalize': capitalize });
       * _.capitalize('fred');
       * // => 'Fred'
       *
       * _('fred').capitalize().value();
       * // => 'Fred'
       *
       * _.mixin({ 'capitalize': capitalize }, { 'chain': false });
       * _('fred').capitalize();
       * // => 'Fred'
       */
      function mixin(object, source, options) {
        var chain = true,
            methodNames = source && functions(source);
  
        if (!source || (!options && !methodNames.length)) {
          if (options == null) {
            options = source;
          }
          ctor = lodashWrapper;
          source = object;
          object = lodash;
          methodNames = functions(source);
        }
        if (options === false) {
          chain = false;
        } else if (isObject(options) && 'chain' in options) {
          chain = options.chain;
        }
        var ctor = object,
            isFunc = isFunction(ctor);
  
        forEach(methodNames, function(methodName) {
          var func = object[methodName] = source[methodName];
          if (isFunc) {
            ctor.prototype[methodName] = function() {
              var chainAll = this.__chain__,
                  value = this.__wrapped__,
                  args = [value];
  
              push.apply(args, arguments);
              var result = func.apply(object, args);
              if (chain || chainAll) {
                if (value === result && isObject(result)) {
                  return this;
                }
                result = new ctor(result);
                result.__chain__ = chainAll;
              }
              return result;
            };
          }
        });
      }
  
      /**
       * Reverts the '_' variable to its previous value and returns a reference to
       * the `lodash` function.
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @returns {Function} Returns the `lodash` function.
       * @example
       *
       * var lodash = _.noConflict();
       */
      function noConflict() {
        context._ = oldDash;
        return this;
      }
  
      /**
       * A no-operation function.
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @example
       *
       * var object = { 'name': 'fred' };
       * _.noop(object) === undefined;
       * // => true
       */
      function noop() {
        // no operation performed
      }
  
      /**
       * Gets the number of milliseconds that have elapsed since the Unix epoch
       * (1 January 1970 00:00:00 UTC).
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @example
       *
       * var stamp = _.now();
       * _.defer(function() { console.log(_.now() - stamp); });
       * // => logs the number of milliseconds it took for the deferred function to be called
       */
      var now = isNative(now = Date.now) && now || function() {
        return new Date().getTime();
      };
  
      /**
       * Converts the given value into an integer of the specified radix.
       * If `radix` is `undefined` or `0` a `radix` of `10` is used unless the
       * `value` is a hexadecimal, in which case a `radix` of `16` is used.
       *
       * Note: This method avoids differences in native ES3 and ES5 `parseInt`
       * implementations. See http://es5.github.io/#E.
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @param {string} value The value to parse.
       * @param {number} [radix] The radix used to interpret the value to parse.
       * @returns {number} Returns the new integer value.
       * @example
       *
       * _.parseInt('08');
       * // => 8
       */
      var parseInt = nativeParseInt(whitespace + '08') == 8 ? nativeParseInt : function(value, radix) {
        // Firefox < 21 and Opera < 15 follow the ES3 specified implementation of `parseInt`
        return nativeParseInt(isString(value) ? value.replace(reLeadingSpacesAndZeros, '') : value, radix || 0);
      };
  
      /**
       * Creates a "_.pluck" style function, which returns the `key` value of a
       * given object.
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @param {string} key The name of the property to retrieve.
       * @returns {Function} Returns the new function.
       * @example
       *
       * var characters = [
       *   { 'name': 'fred',   'age': 40 },
       *   { 'name': 'barney', 'age': 36 }
       * ];
       *
       * var getName = _.property('name');
       *
       * _.map(characters, getName);
       * // => ['barney', 'fred']
       *
       * _.sortBy(characters, getName);
       * // => [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred',   'age': 40 }]
       */
      function property(key) {
        return function(object) {
          return object[key];
        };
      }
  
      /**
       * Produces a random number between `min` and `max` (inclusive). If only one
       * argument is provided a number between `0` and the given number will be
       * returned. If `floating` is truey or either `min` or `max` are floats a
       * floating-point number will be returned instead of an integer.
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @param {number} [min=0] The minimum possible value.
       * @param {number} [max=1] The maximum possible value.
       * @param {boolean} [floating=false] Specify returning a floating-point number.
       * @returns {number} Returns a random number.
       * @example
       *
       * _.random(0, 5);
       * // => an integer between 0 and 5
       *
       * _.random(5);
       * // => also an integer between 0 and 5
       *
       * _.random(5, true);
       * // => a floating-point number between 0 and 5
       *
       * _.random(1.2, 5.2);
       * // => a floating-point number between 1.2 and 5.2
       */
      function random(min, max, floating) {
        var noMin = min == null,
            noMax = max == null;
  
        if (floating == null) {
          if (typeof min == 'boolean' && noMax) {
            floating = min;
            min = 1;
          }
          else if (!noMax && typeof max == 'boolean') {
            floating = max;
            noMax = true;
          }
        }
        if (noMin && noMax) {
          max = 1;
        }
        min = +min || 0;
        if (noMax) {
          max = min;
          min = 0;
        } else {
          max = +max || 0;
        }
        if (floating || min % 1 || max % 1) {
          var rand = nativeRandom();
          return nativeMin(min + (rand * (max - min + parseFloat('1e-' + ((rand +'').length - 1)))), max);
        }
        return baseRandom(min, max);
      }
  
      /**
       * Resolves the value of property `key` on `object`. If `key` is a function
       * it will be invoked with the `this` binding of `object` and its result returned,
       * else the property value is returned. If `object` is falsey then `undefined`
       * is returned.
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @param {Object} object The object to inspect.
       * @param {string} key The name of the property to resolve.
       * @returns {*} Returns the resolved value.
       * @example
       *
       * var object = {
       *   'cheese': 'crumpets',
       *   'stuff': function() {
       *     return 'nonsense';
       *   }
       * };
       *
       * _.result(object, 'cheese');
       * // => 'crumpets'
       *
       * _.result(object, 'stuff');
       * // => 'nonsense'
       */
      function result(object, key) {
        if (object) {
          var value = object[key];
          return isFunction(value) ? object[key]() : value;
        }
      }
  
      /**
       * A micro-templating method that handles arbitrary delimiters, preserves
       * whitespace, and correctly escapes quotes within interpolated code.
       *
       * Note: In the development build, `_.template` utilizes sourceURLs for easier
       * debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
       *
       * For more information on precompiling templates see:
       * http://lodash.com/custom-builds
       *
       * For more information on Chrome extension sandboxes see:
       * http://developer.chrome.com/stable/extensions/sandboxingEval.html
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @param {string} text The template text.
       * @param {Object} data The data object used to populate the text.
       * @param {Object} [options] The options object.
       * @param {RegExp} [options.escape] The "escape" delimiter.
       * @param {RegExp} [options.evaluate] The "evaluate" delimiter.
       * @param {Object} [options.imports] An object to import into the template as local variables.
       * @param {RegExp} [options.interpolate] The "interpolate" delimiter.
       * @param {string} [sourceURL] The sourceURL of the template's compiled source.
       * @param {string} [variable] The data object variable name.
       * @returns {Function|string} Returns a compiled function when no `data` object
       *  is given, else it returns the interpolated text.
       * @example
       *
       * // using the "interpolate" delimiter to create a compiled template
       * var compiled = _.template('hello <%= name %>');
       * compiled({ 'name': 'fred' });
       * // => 'hello fred'
       *
       * // using the "escape" delimiter to escape HTML in data property values
       * _.template('<b><%- value %></b>', { 'value': '<script>' });
       * // => '<b>&lt;script&gt;</b>'
       *
       * // using the "evaluate" delimiter to generate HTML
       * var list = '<% _.forEach(people, function(name) { %><li><%- name %></li><% }); %>';
       * _.template(list, { 'people': ['fred', 'barney'] });
       * // => '<li>fred</li><li>barney</li>'
       *
       * // using the ES6 delimiter as an alternative to the default "interpolate" delimiter
       * _.template('hello ${ name }', { 'name': 'pebbles' });
       * // => 'hello pebbles'
       *
       * // using the internal `print` function in "evaluate" delimiters
       * _.template('<% print("hello " + name); %>!', { 'name': 'barney' });
       * // => 'hello barney!'
       *
       * // using a custom template delimiters
       * _.templateSettings = {
       *   'interpolate': /{{([\s\S]+?)}}/g
       * };
       *
       * _.template('hello {{ name }}!', { 'name': 'mustache' });
       * // => 'hello mustache!'
       *
       * // using the `imports` option to import jQuery
       * var list = '<% jq.each(people, function(name) { %><li><%- name %></li><% }); %>';
       * _.template(list, { 'people': ['fred', 'barney'] }, { 'imports': { 'jq': jQuery } });
       * // => '<li>fred</li><li>barney</li>'
       *
       * // using the `sourceURL` option to specify a custom sourceURL for the template
       * var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' });
       * compiled(data);
       * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
       *
       * // using the `variable` option to ensure a with-statement isn't used in the compiled template
       * var compiled = _.template('hi <%= data.name %>!', null, { 'variable': 'data' });
       * compiled.source;
       * // => function(data) {
       *   var __t, __p = '', __e = _.escape;
       *   __p += 'hi ' + ((__t = ( data.name )) == null ? '' : __t) + '!';
       *   return __p;
       * }
       *
       * // using the `source` property to inline compiled templates for meaningful
       * // line numbers in error messages and a stack trace
       * fs.writeFileSync(path.join(cwd, 'jst.js'), '\
       *   var JST = {\
       *     "main": ' + _.template(mainText).source + '\
       *   };\
       * ');
       */
      function template(text, data, options) {
        // based on John Resig's `tmpl` implementation
        // http://ejohn.org/blog/javascript-micro-templating/
        // and Laura Doktorova's doT.js
        // https://github.com/olado/doT
        var settings = lodash.templateSettings;
        text = String(text || '');
  
        // avoid missing dependencies when `iteratorTemplate` is not defined
        options = defaults({}, options, settings);
  
        var imports = defaults({}, options.imports, settings.imports),
            importsKeys = keys(imports),
            importsValues = values(imports);
  
        var isEvaluating,
            index = 0,
            interpolate = options.interpolate || reNoMatch,
            source = "__p += '";
  
        // compile the regexp to match each delimiter
        var reDelimiters = RegExp(
          (options.escape || reNoMatch).source + '|' +
          interpolate.source + '|' +
          (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
          (options.evaluate || reNoMatch).source + '|$'
        , 'g');
  
        text.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
          interpolateValue || (interpolateValue = esTemplateValue);
  
          // escape characters that cannot be included in string literals
          source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);
  
          // replace delimiters with snippets
          if (escapeValue) {
            source += "' +\n__e(" + escapeValue + ") +\n'";
          }
          if (evaluateValue) {
            isEvaluating = true;
            source += "';\n" + evaluateValue + ";\n__p += '";
          }
          if (interpolateValue) {
            source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
          }
          index = offset + match.length;
  
          // the JS engine embedded in Adobe products requires returning the `match`
          // string in order to produce the correct `offset` value
          return match;
        });
  
        source += "';\n";
  
        // if `variable` is not specified, wrap a with-statement around the generated
        // code to add the data object to the top of the scope chain
        var variable = options.variable,
            hasVariable = variable;
  
        if (!hasVariable) {
          variable = 'obj';
          source = 'with (' + variable + ') {\n' + source + '\n}\n';
        }
        // cleanup code by stripping empty strings
        source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
          .replace(reEmptyStringMiddle, '$1')
          .replace(reEmptyStringTrailing, '$1;');
  
        // frame code as the function body
        source = 'function(' + variable + ') {\n' +
          (hasVariable ? '' : variable + ' || (' + variable + ' = {});\n') +
          "var __t, __p = '', __e = _.escape" +
          (isEvaluating
            ? ', __j = Array.prototype.join;\n' +
              "function print() { __p += __j.call(arguments, '') }\n"
            : ';\n'
          ) +
          source +
          'return __p\n}';
  
        // Use a sourceURL for easier debugging.
        // http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
        var sourceURL = '\n/*\n//# sourceURL=' + (options.sourceURL || '/lodash/template/source[' + (templateCounter++) + ']') + '\n*/';
  
        try {
          var result = Function(importsKeys, 'return ' + source + sourceURL).apply(undefined, importsValues);
        } catch(e) {
          e.source = source;
          throw e;
        }
        if (data) {
          return result(data);
        }
        // provide the compiled function's source by its `toString` method, in
        // supported environments, or the `source` property as a convenience for
        // inlining compiled templates during the build process
        result.source = source;
        return result;
      }
  
      /**
       * Executes the callback `n` times, returning an array of the results
       * of each callback execution. The callback is bound to `thisArg` and invoked
       * with one argument; (index).
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @param {number} n The number of times to execute the callback.
       * @param {Function} callback The function called per iteration.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Array} Returns an array of the results of each `callback` execution.
       * @example
       *
       * var diceRolls = _.times(3, _.partial(_.random, 1, 6));
       * // => [3, 6, 4]
       *
       * _.times(3, function(n) { mage.castSpell(n); });
       * // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively
       *
       * _.times(3, function(n) { this.cast(n); }, mage);
       * // => also calls `mage.castSpell(n)` three times
       */
      function times(n, callback, thisArg) {
        n = (n = +n) > -1 ? n : 0;
        var index = -1,
            result = Array(n);
  
        callback = baseCreateCallback(callback, thisArg, 1);
        while (++index < n) {
          result[index] = callback(index);
        }
        return result;
      }
  
      /**
       * The inverse of `_.escape` this method converts the HTML entities
       * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to their
       * corresponding characters.
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @param {string} string The string to unescape.
       * @returns {string} Returns the unescaped string.
       * @example
       *
       * _.unescape('Fred, Barney &amp; Pebbles');
       * // => 'Fred, Barney & Pebbles'
       */
      function unescape(string) {
        return string == null ? '' : String(string).replace(reEscapedHtml, unescapeHtmlChar);
      }
  
      /**
       * Generates a unique ID. If `prefix` is provided the ID will be appended to it.
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @param {string} [prefix] The value to prefix the ID with.
       * @returns {string} Returns the unique ID.
       * @example
       *
       * _.uniqueId('contact_');
       * // => 'contact_104'
       *
       * _.uniqueId();
       * // => '105'
       */
      function uniqueId(prefix) {
        var id = ++idCounter;
        return String(prefix == null ? '' : prefix) + id;
      }
  
      /*--------------------------------------------------------------------------*/
  
      /**
       * Creates a `lodash` object that wraps the given value with explicit
       * method chaining enabled.
       *
       * @static
       * @memberOf _
       * @category Chaining
       * @param {*} value The value to wrap.
       * @returns {Object} Returns the wrapper object.
       * @example
       *
       * var characters = [
       *   { 'name': 'barney',  'age': 36 },
       *   { 'name': 'fred',    'age': 40 },
       *   { 'name': 'pebbles', 'age': 1 }
       * ];
       *
       * var youngest = _.chain(characters)
       *     .sortBy('age')
       *     .map(function(chr) { return chr.name + ' is ' + chr.age; })
       *     .first()
       *     .value();
       * // => 'pebbles is 1'
       */
      function chain(value) {
        value = new lodashWrapper(value);
        value.__chain__ = true;
        return value;
      }
  
      /**
       * Invokes `interceptor` with the `value` as the first argument and then
       * returns `value`. The purpose of this method is to "tap into" a method
       * chain in order to perform operations on intermediate results within
       * the chain.
       *
       * @static
       * @memberOf _
       * @category Chaining
       * @param {*} value The value to provide to `interceptor`.
       * @param {Function} interceptor The function to invoke.
       * @returns {*} Returns `value`.
       * @example
       *
       * _([1, 2, 3, 4])
       *  .tap(function(array) { array.pop(); })
       *  .reverse()
       *  .value();
       * // => [3, 2, 1]
       */
      function tap(value, interceptor) {
        interceptor(value);
        return value;
      }
  
      /**
       * Enables explicit method chaining on the wrapper object.
       *
       * @name chain
       * @memberOf _
       * @category Chaining
       * @returns {*} Returns the wrapper object.
       * @example
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 36 },
       *   { 'name': 'fred',   'age': 40 }
       * ];
       *
       * // without explicit chaining
       * _(characters).first();
       * // => { 'name': 'barney', 'age': 36 }
       *
       * // with explicit chaining
       * _(characters).chain()
       *   .first()
       *   .pick('age')
       *   .value();
       * // => { 'age': 36 }
       */
      function wrapperChain() {
        this.__chain__ = true;
        return this;
      }
  
      /**
       * Produces the `toString` result of the wrapped value.
       *
       * @name toString
       * @memberOf _
       * @category Chaining
       * @returns {string} Returns the string result.
       * @example
       *
       * _([1, 2, 3]).toString();
       * // => '1,2,3'
       */
      function wrapperToString() {
        return String(this.__wrapped__);
      }
  
      /**
       * Extracts the wrapped value.
       *
       * @name valueOf
       * @memberOf _
       * @alias value
       * @category Chaining
       * @returns {*} Returns the wrapped value.
       * @example
       *
       * _([1, 2, 3]).valueOf();
       * // => [1, 2, 3]
       */
      function wrapperValueOf() {
        return this.__wrapped__;
      }
  
      /*--------------------------------------------------------------------------*/
  
      // add functions that return wrapped values when chaining
      lodash.after = after;
      lodash.assign = assign;
      lodash.at = at;
      lodash.bind = bind;
      lodash.bindAll = bindAll;
      lodash.bindKey = bindKey;
      lodash.chain = chain;
      lodash.compact = compact;
      lodash.compose = compose;
      lodash.constant = constant;
      lodash.countBy = countBy;
      lodash.create = create;
      lodash.createCallback = createCallback;
      lodash.curry = curry;
      lodash.debounce = debounce;
      lodash.defaults = defaults;
      lodash.defer = defer;
      lodash.delay = delay;
      lodash.difference = difference;
      lodash.filter = filter;
      lodash.flatten = flatten;
      lodash.forEach = forEach;
      lodash.forEachRight = forEachRight;
      lodash.forIn = forIn;
      lodash.forInRight = forInRight;
      lodash.forOwn = forOwn;
      lodash.forOwnRight = forOwnRight;
      lodash.functions = functions;
      lodash.groupBy = groupBy;
      lodash.indexBy = indexBy;
      lodash.initial = initial;
      lodash.intersection = intersection;
      lodash.invert = invert;
      lodash.invoke = invoke;
      lodash.keys = keys;
      lodash.map = map;
      lodash.mapValues = mapValues;
      lodash.max = max;
      lodash.memoize = memoize;
      lodash.merge = merge;
      lodash.min = min;
      lodash.omit = omit;
      lodash.once = once;
      lodash.pairs = pairs;
      lodash.partial = partial;
      lodash.partialRight = partialRight;
      lodash.pick = pick;
      lodash.pluck = pluck;
      lodash.property = property;
      lodash.pull = pull;
      lodash.range = range;
      lodash.reject = reject;
      lodash.remove = remove;
      lodash.rest = rest;
      lodash.shuffle = shuffle;
      lodash.sortBy = sortBy;
      lodash.tap = tap;
      lodash.throttle = throttle;
      lodash.times = times;
      lodash.toArray = toArray;
      lodash.transform = transform;
      lodash.union = union;
      lodash.uniq = uniq;
      lodash.values = values;
      lodash.where = where;
      lodash.without = without;
      lodash.wrap = wrap;
      lodash.xor = xor;
      lodash.zip = zip;
      lodash.zipObject = zipObject;
  
      // add aliases
      lodash.collect = map;
      lodash.drop = rest;
      lodash.each = forEach;
      lodash.eachRight = forEachRight;
      lodash.extend = assign;
      lodash.methods = functions;
      lodash.object = zipObject;
      lodash.select = filter;
      lodash.tail = rest;
      lodash.unique = uniq;
      lodash.unzip = zip;
  
      // add functions to `lodash.prototype`
      mixin(lodash);
  
      /*--------------------------------------------------------------------------*/
  
      // add functions that return unwrapped values when chaining
      lodash.clone = clone;
      lodash.cloneDeep = cloneDeep;
      lodash.contains = contains;
      lodash.escape = escape;
      lodash.every = every;
      lodash.find = find;
      lodash.findIndex = findIndex;
      lodash.findKey = findKey;
      lodash.findLast = findLast;
      lodash.findLastIndex = findLastIndex;
      lodash.findLastKey = findLastKey;
      lodash.has = has;
      lodash.identity = identity;
      lodash.indexOf = indexOf;
      lodash.isArguments = isArguments;
      lodash.isArray = isArray;
      lodash.isBoolean = isBoolean;
      lodash.isDate = isDate;
      lodash.isElement = isElement;
      lodash.isEmpty = isEmpty;
      lodash.isEqual = isEqual;
      lodash.isFinite = isFinite;
      lodash.isFunction = isFunction;
      lodash.isNaN = isNaN;
      lodash.isNull = isNull;
      lodash.isNumber = isNumber;
      lodash.isObject = isObject;
      lodash.isPlainObject = isPlainObject;
      lodash.isRegExp = isRegExp;
      lodash.isString = isString;
      lodash.isUndefined = isUndefined;
      lodash.lastIndexOf = lastIndexOf;
      lodash.mixin = mixin;
      lodash.noConflict = noConflict;
      lodash.noop = noop;
      lodash.now = now;
      lodash.parseInt = parseInt;
      lodash.random = random;
      lodash.reduce = reduce;
      lodash.reduceRight = reduceRight;
      lodash.result = result;
      lodash.runInContext = runInContext;
      lodash.size = size;
      lodash.some = some;
      lodash.sortedIndex = sortedIndex;
      lodash.template = template;
      lodash.unescape = unescape;
      lodash.uniqueId = uniqueId;
  
      // add aliases
      lodash.all = every;
      lodash.any = some;
      lodash.detect = find;
      lodash.findWhere = find;
      lodash.foldl = reduce;
      lodash.foldr = reduceRight;
      lodash.include = contains;
      lodash.inject = reduce;
  
      mixin(function() {
        var source = {}
        forOwn(lodash, function(func, methodName) {
          if (!lodash.prototype[methodName]) {
            source[methodName] = func;
          }
        });
        return source;
      }(), false);
  
      /*--------------------------------------------------------------------------*/
  
      // add functions capable of returning wrapped and unwrapped values when chaining
      lodash.first = first;
      lodash.last = last;
      lodash.sample = sample;
  
      // add aliases
      lodash.take = first;
      lodash.head = first;
  
      forOwn(lodash, function(func, methodName) {
        var callbackable = methodName !== 'sample';
        if (!lodash.prototype[methodName]) {
          lodash.prototype[methodName]= function(n, guard) {
            var chainAll = this.__chain__,
                result = func(this.__wrapped__, n, guard);
  
            return !chainAll && (n == null || (guard && !(callbackable && typeof n == 'function')))
              ? result
              : new lodashWrapper(result, chainAll);
          };
        }
      });
  
      /*--------------------------------------------------------------------------*/
  
      /**
       * The semantic version number.
       *
       * @static
       * @memberOf _
       * @type string
       */
      lodash.VERSION = '2.4.1';
  
      // add "Chaining" functions to the wrapper
      lodash.prototype.chain = wrapperChain;
      lodash.prototype.toString = wrapperToString;
      lodash.prototype.value = wrapperValueOf;
      lodash.prototype.valueOf = wrapperValueOf;
  
      // add `Array` functions that return unwrapped values
      forEach(['join', 'pop', 'shift'], function(methodName) {
        var func = arrayRef[methodName];
        lodash.prototype[methodName] = function() {
          var chainAll = this.__chain__,
              result = func.apply(this.__wrapped__, arguments);
  
          return chainAll
            ? new lodashWrapper(result, chainAll)
            : result;
        };
      });
  
      // add `Array` functions that return the existing wrapped value
      forEach(['push', 'reverse', 'sort', 'unshift'], function(methodName) {
        var func = arrayRef[methodName];
        lodash.prototype[methodName] = function() {
          func.apply(this.__wrapped__, arguments);
          return this;
        };
      });
  
      // add `Array` functions that return new wrapped values
      forEach(['concat', 'slice', 'splice'], function(methodName) {
        var func = arrayRef[methodName];
        lodash.prototype[methodName] = function() {
          return new lodashWrapper(func.apply(this.__wrapped__, arguments), this.__chain__);
        };
      });
  
      return lodash;
    }
  
    /*--------------------------------------------------------------------------*/
  
    // expose Lo-Dash
    var _ = runInContext();
  
    // some AMD build optimizers like r.js check for condition patterns like the following:
    if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
      // Expose Lo-Dash to the global object even when an AMD loader is present in
      // case Lo-Dash is loaded with a RequireJS shim config.
      // See http://requirejs.org/docs/api.html#config-shim
      root._ = _;
  
      // define as an anonymous module so, through path mapping, it can be
      // referenced as the "underscore" module
      define(function() {
        return _;
      });
    }
    // check for `exports` after `define` in case a build optimizer adds an `exports` object
    else if (freeExports && freeModule) {
      // in Node.js or RingoJS
      if (moduleExports) {
        (freeModule.exports = _)._ = _;
      }
      // in Narwhal or Rhino -require
      else {
        freeExports._ = _;
      }
    }
    else {
      // in a browser or Rhino
      root._ = _;
    }
  }.call(this));
  
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{}],100:[function(require,module,exports){
  (function (process){
  var path = require('path');
  var fs = require('fs');
  var _0777 = parseInt('0777', 8);
  
  module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP;
  
  function mkdirP (p, opts, f, made) {
      if (typeof opts === 'function') {
          f = opts;
          opts = {};
      }
      else if (!opts || typeof opts !== 'object') {
          opts = { mode: opts };
      }
      
      var mode = opts.mode;
      var xfs = opts.fs || fs;
      
      if (mode === undefined) {
          mode = _0777 & (~process.umask());
      }
      if (!made) made = null;
      
      var cb = f || function () {};
      p = path.resolve(p);
      
      xfs.mkdir(p, mode, function (er) {
          if (!er) {
              made = made || p;
              return cb(null, made);
          }
          switch (er.code) {
              case 'ENOENT':
                  mkdirP(path.dirname(p), opts, function (er, made) {
                      if (er) cb(er, made);
                      else mkdirP(p, opts, cb, made);
                  });
                  break;
  
              // In the case of any other error, just see if there's a dir
              // there already.  If so, then hooray!  If not, then something
              // is borked.
              default:
                  xfs.stat(p, function (er2, stat) {
                      // if the stat fails, then that's super weird.
                      // let the original error be the failure reason.
                      if (er2 || !stat.isDirectory()) cb(er, made)
                      else cb(null, made);
                  });
                  break;
          }
      });
  }
  
  mkdirP.sync = function sync (p, opts, made) {
      if (!opts || typeof opts !== 'object') {
          opts = { mode: opts };
      }
      
      var mode = opts.mode;
      var xfs = opts.fs || fs;
      
      if (mode === undefined) {
          mode = _0777 & (~process.umask());
      }
      if (!made) made = null;
  
      p = path.resolve(p);
  
      try {
          xfs.mkdirSync(p, mode);
          made = made || p;
      }
      catch (err0) {
          switch (err0.code) {
              case 'ENOENT' :
                  made = sync(path.dirname(p), opts, made);
                  sync(p, opts, made);
                  break;
  
              // In the case of any other error, just see if there's a dir
              // there already.  If so, then hooray!  If not, then something
              // is borked.
              default:
                  var stat;
                  try {
                      stat = xfs.statSync(p);
                  }
                  catch (err1) {
                      throw err0;
                  }
                  if (!stat.isDirectory()) throw err0;
                  break;
          }
      }
  
      return made;
  };
  
  }).call(this,require('_process'))
  },{"_process":25,"fs":12,"path":24}],101:[function(require,module,exports){
  function propagate(events, source, dest) {
    if (arguments.length < 3) {
      dest = source;
      source = events;
      events = undefined;
    }
  
    // events should be an array
    if (events && ! Array.isArray(events)) events = [events];
  
    if (Array.isArray(events)) {
      return explicitPropagate(events, source, dest);
    }
  
    var oldEmit =  source.emit;
  
    source.emit = function(eventType) {
      if (! events || ~events.indexOf(eventType)) {
        dest.emit.apply(dest, arguments);
      }
      oldEmit.apply(source, arguments);
    }
  
    function end() {
      source.emit = oldEmit;
    }
  
    return {
      end: end
    };
  };
  
  module.exports = propagate;
  
  function explicitPropagate(events, source, dest) {
  
    var listeners = events.map(function(event) {
      return function() {
        var args = Array.prototype.slice(arguments);
        args.unshift(event);
        dest.emit.apply(dest, args);
      }
    });
  
    listeners.forEach(register);
  
    return {
      end: end
    };
  
    function register(listener, i) {
      source.on(events[i], listener);
    }
  
    function unregister(listener, i) {
      source.removeListener(events[i], listener);
    }
  
    function end() {
      listeners.forEach(unregister);
    }
  }
  },{}],102:[function(require,module,exports){
  var assert = require('assert');
  var http = require('http');
  var nock = require('../../');
  
  nock.disableNetConnect();
  nock('http://browserifyland.com').get('/beep').reply(200, 'boop');
  
  http.get('http://browserifyland.com/beep', function(res) {
    res.setEncoding('utf8');
    var body = '';
    res
      .on('data', function(d) {
        body += d;
      })
      .once('end', function() {
        assert.equal(body, 'boop');
        document.getElementById('content').innerHTML = body;
      });
  });
  },{"../../":1,"assert":13,"http":44}]},{},[102]);
  