text: /*!
   * https://github.com/es-shims/es5-shim
   * @license es5-shim Copyright 2009-2015 by contributors, MIT License
   * see https://github.com/es-shims/es5-shim/blob/master/LICENSE
   */
  
  // vim: ts=4 sts=4 sw=4 expandtab
  
  // Add semicolon to prevent IIFE from being passed as argument to concatenated code.
  ;
  
  // UMD (Universal Module Definition)
  // see https://github.com/umdjs/umd/blob/master/returnExports.js
  (function (root, factory) {
      'use strict';
  
      /* global define, exports, module */
      if (typeof define === 'function' && define.amd) {
          // AMD. Register as an anonymous module.
          define(factory);
      } else if (typeof exports === 'object') {
          // Node. Does not work with strict CommonJS, but
          // only CommonJS-like enviroments that support module.exports,
          // like Node.
          module.exports = factory();
      } else {
          // Browser globals (root is window)
          root.returnExports = factory();
      }
  }(this, function () {
  
  /**
   * Brings an environment as close to ECMAScript 5 compliance
   * as is possible with the facilities of erstwhile engines.
   *
   * Annotated ES5: http://es5.github.com/ (specific links below)
   * ES5 Spec: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
   * Required reading: http://javascriptweblog.wordpress.com/2011/12/05/extending-javascript-natives/
   */
  
  // Shortcut to an often accessed properties, in order to avoid multiple
  // dereference that costs universally. This also holds a reference to known-good
  // functions.
  var $Array = Array;
  var ArrayPrototype = $Array.prototype;
  var $Object = Object;
  var ObjectPrototype = $Object.prototype;
  var FunctionPrototype = Function.prototype;
  var $String = String;
  var StringPrototype = $String.prototype;
  var $Number = Number;
  var NumberPrototype = $Number.prototype;
  var array_slice = ArrayPrototype.slice;
  var array_splice = ArrayPrototype.splice;
  var array_push = ArrayPrototype.push;
  var array_unshift = ArrayPrototype.unshift;
  var array_concat = ArrayPrototype.concat;
  var call = FunctionPrototype.call;
  var max = Math.max;
  var min = Math.min;
  
  // Having a toString local variable name breaks in Opera so use to_string.
  var to_string = ObjectPrototype.toString;
  
  var hasToStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol';
  var isCallable; /* inlined from https://npmjs.com/is-callable */ var fnToStr = Function.prototype.toString, tryFunctionObject = function tryFunctionObject(value) { try { fnToStr.call(value); return true; } catch (e) { return false; } }, fnClass = '[object Function]', genClass = '[object GeneratorFunction]'; isCallable = function isCallable(value) { if (typeof value !== 'function') { return false; } if (hasToStringTag) { return tryFunctionObject(value); } var strClass = to_string.call(value); return strClass === fnClass || strClass === genClass; };
  var isRegex; /* inlined from https://npmjs.com/is-regex */ var regexExec = RegExp.prototype.exec, tryRegexExec = function tryRegexExec(value) { try { regexExec.call(value); return true; } catch (e) { return false; } }, regexClass = '[object RegExp]'; isRegex = function isRegex(value) { if (typeof value !== 'object') { return false; } return hasToStringTag ? tryRegexExec(value) : to_string.call(value) === regexClass; };
  var isString; /* inlined from https://npmjs.com/is-string */ var strValue = String.prototype.valueOf, tryStringObject = function tryStringObject(value) { try { strValue.call(value); return true; } catch (e) { return false; } }, stringClass = '[object String]'; isString = function isString(value) { if (typeof value === 'string') { return true; } if (typeof value !== 'object') { return false; } return hasToStringTag ? tryStringObject(value) : to_string.call(value) === stringClass; };
  
  /* inlined from http://npmjs.com/define-properties */
  var defineProperties = (function (has) {
    var supportsDescriptors = $Object.defineProperty && (function () {
        try {
            var obj = {};
            $Object.defineProperty(obj, 'x', { enumerable: false, value: obj });
            for (var _ in obj) { return false; }
            return obj.x === obj;
        } catch (e) { /* this is ES3 */
            return false;
        }
    }());
  
    // Define configurable, writable and non-enumerable props
    // if they don't exist.
    var defineProperty;
    if (supportsDescriptors) {
        defineProperty = function (object, name, method, forceAssign) {
            if (!forceAssign && (name in object)) { return; }
            $Object.defineProperty(object, name, {
                configurable: true,
                enumerable: false,
                writable: true,
                value: method
            });
        };
    } else {
        defineProperty = function (object, name, method, forceAssign) {
            if (!forceAssign && (name in object)) { return; }
            object[name] = method;
        };
    }
    return function defineProperties(object, map, forceAssign) {
        for (var name in map) {
            if (has.call(map, name)) {
              defineProperty(object, name, map[name], forceAssign);
            }
        }
    };
  }(ObjectPrototype.hasOwnProperty));
  
  //
  // Util
  // ======
  //
  
  /* replaceable with https://npmjs.com/package/es-abstract /helpers/isPrimitive */
  var isPrimitive = function isPrimitive(input) {
      var type = typeof input;
      return input === null || (type !== 'object' && type !== 'function');
  };
  
  var ES = {
      // ES5 9.4
      // http://es5.github.com/#x9.4
      // http://jsperf.com/to-integer
      /* replaceable with https://npmjs.com/package/es-abstract ES5.ToInteger */
      ToInteger: function ToInteger(num) {
          var n = +num;
          if (n !== n) { // isNaN
              n = 0;
          } else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) {
              n = (n > 0 || -1) * Math.floor(Math.abs(n));
          }
          return n;
      },
  
      /* replaceable with https://npmjs.com/package/es-abstract ES5.ToPrimitive */
      ToPrimitive: function ToPrimitive(input) {
          var val, valueOf, toStr;
          if (isPrimitive(input)) {
              return input;
          }
          valueOf = input.valueOf;
          if (isCallable(valueOf)) {
              val = valueOf.call(input);
              if (isPrimitive(val)) {
                  return val;
              }
          }
          toStr = input.toString;
          if (isCallable(toStr)) {
              val = toStr.call(input);
              if (isPrimitive(val)) {
                  return val;
              }
          }
          throw new TypeError();
      },
  
      // ES5 9.9
      // http://es5.github.com/#x9.9
      /* replaceable with https://npmjs.com/package/es-abstract ES5.ToObject */
      ToObject: function (o) {
          /* jshint eqnull: true */
          if (o == null) { // this matches both null and undefined
              throw new TypeError("can't convert " + o + ' to object');
          }
          return $Object(o);
      },
  
      /* replaceable with https://npmjs.com/package/es-abstract ES5.ToUint32 */
      ToUint32: function ToUint32(x) {
          return x >>> 0;
      }
  };
  
  //
  // Function
  // ========
  //
  
  // ES-5 15.3.4.5
  // http://es5.github.com/#x15.3.4.5
  
  var Empty = function Empty() {};
  
  defineProperties(FunctionPrototype, {
      bind: function bind(that) { // .length is 1
          // 1. Let Target be the this value.
          var target = this;
          // 2. If IsCallable(Target) is false, throw a TypeError exception.
          if (!isCallable(target)) {
              throw new TypeError('Function.prototype.bind called on incompatible ' + target);
          }
          // 3. Let A be a new (possibly empty) internal list of all of the
          //   argument values provided after thisArg (arg1, arg2 etc), in order.
          // XXX slicedArgs will stand in for "A" if used
          var args = array_slice.call(arguments, 1); // for normal call
          // 4. Let F be a new native ECMAScript object.
          // 11. Set the [[Prototype]] internal property of F to the standard
          //   built-in Function prototype object as specified in 15.3.3.1.
          // 12. Set the [[Call]] internal property of F as described in
          //   15.3.4.5.1.
          // 13. Set the [[Construct]] internal property of F as described in
          //   15.3.4.5.2.
          // 14. Set the [[HasInstance]] internal property of F as described in
          //   15.3.4.5.3.
          var bound;
          var binder = function () {
  
              if (this instanceof bound) {
                  // 15.3.4.5.2 [[Construct]]
                  // When the [[Construct]] internal method of a function object,
                  // F that was created using the bind function is called with a
                  // list of arguments ExtraArgs, the following steps are taken:
                  // 1. Let target be the value of F's [[TargetFunction]]
                  //   internal property.
                  // 2. If target has no [[Construct]] internal method, a
                  //   TypeError exception is thrown.
                  // 3. Let boundArgs be the value of F's [[BoundArgs]] internal
                  //   property.
                  // 4. Let args be a new list containing the same values as the
                  //   list boundArgs in the same order followed by the same
                  //   values as the list ExtraArgs in the same order.
                  // 5. Return the result of calling the [[Construct]] internal
                  //   method of target providing args as the arguments.
  
                  var result = target.apply(
                      this,
                      array_concat.call(args, array_slice.call(arguments))
                  );
                  if ($Object(result) === result) {
                      return result;
                  }
                  return this;
  
              } else {
                  // 15.3.4.5.1 [[Call]]
                  // When the [[Call]] internal method of a function object, F,
                  // which was created using the bind function is called with a
                  // this value and a list of arguments ExtraArgs, the following
                  // steps are taken:
                  // 1. Let boundArgs be the value of F's [[BoundArgs]] internal
                  //   property.
                  // 2. Let boundThis be the value of F's [[BoundThis]] internal
                  //   property.
                  // 3. Let target be the value of F's [[TargetFunction]] internal
                  //   property.
                  // 4. Let args be a new list containing the same values as the
                  //   list boundArgs in the same order followed by the same
                  //   values as the list ExtraArgs in the same order.
                  // 5. Return the result of calling the [[Call]] internal method
                  //   of target providing boundThis as the this value and
                  //   providing args as the arguments.
  
                  // equiv: target.call(this, ...boundArgs, ...args)
                  return target.apply(
                      that,
                      array_concat.call(args, array_slice.call(arguments))
                  );
  
              }
  
          };
  
          // 15. If the [[Class]] internal property of Target is "Function", then
          //     a. Let L be the length property of Target minus the length of A.
          //     b. Set the length own property of F to either 0 or L, whichever is
          //       larger.
          // 16. Else set the length own property of F to 0.
  
          var boundLength = max(0, target.length - args.length);
  
          // 17. Set the attributes of the length own property of F to the values
          //   specified in 15.3.5.1.
          var boundArgs = [];
          for (var i = 0; i < boundLength; i++) {
              array_push.call(boundArgs, '$' + i);
          }
  
          // XXX Build a dynamic function with desired amount of arguments is the only
          // way to set the length property of a function.
          // In environments where Content Security Policies enabled (Chrome extensions,
          // for ex.) all use of eval or Function costructor throws an exception.
          // However in all of these environments Function.prototype.bind exists
          // and so this code will never be executed.
          bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this, arguments); }')(binder);
  
          if (target.prototype) {
              Empty.prototype = target.prototype;
              bound.prototype = new Empty();
              // Clean up dangling references.
              Empty.prototype = null;
          }
  
          // TODO
          // 18. Set the [[Extensible]] internal property of F to true.
  
          // TODO
          // 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3).
          // 20. Call the [[DefineOwnProperty]] internal method of F with
          //   arguments "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]:
          //   thrower, [[Enumerable]]: false, [[Configurable]]: false}, and
          //   false.
          // 21. Call the [[DefineOwnProperty]] internal method of F with
          //   arguments "arguments", PropertyDescriptor {[[Get]]: thrower,
          //   [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false},
          //   and false.
  
          // TODO
          // NOTE Function objects created using Function.prototype.bind do not
          // have a prototype property or the [[Code]], [[FormalParameters]], and
          // [[Scope]] internal properties.
          // XXX can't delete prototype in pure-js.
  
          // 22. Return F.
          return bound;
      }
  });
  
  // _Please note: Shortcuts are defined after `Function.prototype.bind` as we
  // us it in defining shortcuts.
  var owns = call.bind(ObjectPrototype.hasOwnProperty);
  var toStr = call.bind(ObjectPrototype.toString);
  var strSlice = call.bind(StringPrototype.slice);
  var strSplit = call.bind(StringPrototype.split);
  
  //
  // Array
  // =====
  //
  
  var isArray = $Array.isArray || function isArray(obj) {
      return toStr(obj) === '[object Array]';
  };
  
  // ES5 15.4.4.12
  // http://es5.github.com/#x15.4.4.13
  // Return len+argCount.
  // [bugfix, ielt8]
  // IE < 8 bug: [].unshift(0) === undefined but should be "1"
  var hasUnshiftReturnValueBug = [].unshift(0) !== 1;
  defineProperties(ArrayPrototype, {
      unshift: function () {
          array_unshift.apply(this, arguments);
          return this.length;
      }
  }, hasUnshiftReturnValueBug);
  
  // ES5 15.4.3.2
  // http://es5.github.com/#x15.4.3.2
  // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray
  defineProperties($Array, { isArray: isArray });
  
  // The IsCallable() check in the Array functions
  // has been replaced with a strict check on the
  // internal class of the object to trap cases where
  // the provided function was actually a regular
  // expression literal, which in V8 and
  // JavaScriptCore is a typeof "function".  Only in
  // V8 are regular expression literals permitted as
  // reduce parameters, so it is desirable in the
  // general case for the shim to match the more
  // strict and common behavior of rejecting regular
  // expressions.
  
  // ES5 15.4.4.18
  // http://es5.github.com/#x15.4.4.18
  // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/forEach
  
  // Check failure of by-index access of string characters (IE < 9)
  // and failure of `0 in boxedString` (Rhino)
  var boxedString = $Object('a');
  var splitString = boxedString[0] !== 'a' || !(0 in boxedString);
  
  var properlyBoxesContext = function properlyBoxed(method) {
      // Check node 0.6.21 bug where third parameter is not boxed
      var properlyBoxesNonStrict = true;
      var properlyBoxesStrict = true;
      if (method) {
          method.call('foo', function (_, __, context) {
              if (typeof context !== 'object') { properlyBoxesNonStrict = false; }
          });
  
          method.call([1], function () {
              'use strict';
  
              properlyBoxesStrict = typeof this === 'string';
          }, 'x');
      }
      return !!method && properlyBoxesNonStrict && properlyBoxesStrict;
  };
  
  defineProperties(ArrayPrototype, {
      forEach: function forEach(callbackfn /*, thisArg*/) {
          var object = ES.ToObject(this);
          var self = splitString && isString(this) ? strSplit(this, '') : object;
          var i = -1;
          var length = self.length >>> 0;
          var T;
          if (arguments.length > 1) {
            T = arguments[1];
          }
  
          // If no callback function or if callback is not a callable function
          if (!isCallable(callbackfn)) {
              throw new TypeError('Array.prototype.forEach callback must be a function');
          }
  
          while (++i < length) {
              if (i in self) {
                  // Invoke the callback function with call, passing arguments:
                  // context, property value, property key, thisArg object
                  if (typeof T !== 'undefined') {
                      callbackfn.call(T, self[i], i, object);
                  } else {
                      callbackfn(self[i], i, object);
                  }
              }
          }
      }
  }, !properlyBoxesContext(ArrayPrototype.forEach));
  
  // ES5 15.4.4.19
  // http://es5.github.com/#x15.4.4.19
  // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map
  defineProperties(ArrayPrototype, {
      map: function map(callbackfn/*, thisArg*/) {
          var object = ES.ToObject(this);
          var self = splitString && isString(this) ? strSplit(this, '') : object;
          var length = self.length >>> 0;
          var result = $Array(length);
          var T;
          if (arguments.length > 1) {
              T = arguments[1];
          }
  
          // If no callback function or if callback is not a callable function
          if (!isCallable(callbackfn)) {
              throw new TypeError('Array.prototype.map callback must be a function');
          }
  
          for (var i = 0; i < length; i++) {
              if (i in self) {
                  if (typeof T !== 'undefined') {
                      result[i] = callbackfn.call(T, self[i], i, object);
                  } else {
                      result[i] = callbackfn(self[i], i, object);
                  }
              }
          }
          return result;
      }
  }, !properlyBoxesContext(ArrayPrototype.map));
  
  // ES5 15.4.4.20
  // http://es5.github.com/#x15.4.4.20
  // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter
  defineProperties(ArrayPrototype, {
      filter: function filter(callbackfn /*, thisArg*/) {
          var object = ES.ToObject(this);
          var self = splitString && isString(this) ? strSplit(this, '') : object;
          var length = self.length >>> 0;
          var result = [];
          var value;
          var T;
          if (arguments.length > 1) {
              T = arguments[1];
          }
  
          // If no callback function or if callback is not a callable function
          if (!isCallable(callbackfn)) {
              throw new TypeError('Array.prototype.filter callback must be a function');
          }
  
          for (var i = 0; i < length; i++) {
              if (i in self) {
                  value = self[i];
                  if (typeof T === 'undefined' ? callbackfn(value, i, object) : callbackfn.call(T, value, i, object)) {
                      array_push.call(result, value);
                  }
              }
          }
          return result;
      }
  }, !properlyBoxesContext(ArrayPrototype.filter));
  
  // ES5 15.4.4.16
  // http://es5.github.com/#x15.4.4.16
  // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every
  defineProperties(ArrayPrototype, {
      every: function every(callbackfn /*, thisArg*/) {
          var object = ES.ToObject(this);
          var self = splitString && isString(this) ? strSplit(this, '') : object;
          var length = self.length >>> 0;
          var T;
          if (arguments.length > 1) {
              T = arguments[1];
          }
  
          // If no callback function or if callback is not a callable function
          if (!isCallable(callbackfn)) {
              throw new TypeError('Array.prototype.every callback must be a function');
          }
  
          for (var i = 0; i < length; i++) {
              if (i in self && !(typeof T === 'undefined' ? callbackfn(self[i], i, object) : callbackfn.call(T, self[i], i, object))) {
                  return false;
              }
          }
          return true;
      }
  }, !properlyBoxesContext(ArrayPrototype.every));
  
  // ES5 15.4.4.17
  // http://es5.github.com/#x15.4.4.17
  // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some
  defineProperties(ArrayPrototype, {
      some: function some(callbackfn/*, thisArg */) {
          var object = ES.ToObject(this);
          var self = splitString && isString(this) ? strSplit(this, '') : object;
          var length = self.length >>> 0;
          var T;
          if (arguments.length > 1) {
              T = arguments[1];
          }
  
          // If no callback function or if callback is not a callable function
          if (!isCallable(callbackfn)) {
              throw new TypeError('Array.prototype.some callback must be a function');
          }
  
          for (var i = 0; i < length; i++) {
              if (i in self && (typeof T === 'undefined' ? callbackfn(self[i], i, object) : callbackfn.call(T, self[i], i, object))) {
                  return true;
              }
          }
          return false;
      }
  }, !properlyBoxesContext(ArrayPrototype.some));
  
  // ES5 15.4.4.21
  // http://es5.github.com/#x15.4.4.21
  // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce
  var reduceCoercesToObject = false;
  if (ArrayPrototype.reduce) {
      reduceCoercesToObject = typeof ArrayPrototype.reduce.call('es5', function (_, __, ___, list) { return list; }) === 'object';
  }
  defineProperties(ArrayPrototype, {
      reduce: function reduce(callbackfn /*, initialValue*/) {
          var object = ES.ToObject(this);
          var self = splitString && isString(this) ? strSplit(this, '') : object;
          var length = self.length >>> 0;
  
          // If no callback function or if callback is not a callable function
          if (!isCallable(callbackfn)) {
              throw new TypeError('Array.prototype.reduce callback must be a function');
          }
  
          // no value to return if no initial value and an empty array
          if (length === 0 && arguments.length === 1) {
              throw new TypeError('reduce of empty array with no initial value');
          }
  
          var i = 0;
          var result;
          if (arguments.length >= 2) {
              result = arguments[1];
          } else {
              do {
                  if (i in self) {
                      result = self[i++];
                      break;
                  }
  
                  // if array contains no values, no initial value to return
                  if (++i >= length) {
                      throw new TypeError('reduce of empty array with no initial value');
                  }
              } while (true);
          }
  
          for (; i < length; i++) {
              if (i in self) {
                  result = callbackfn(result, self[i], i, object);
              }
          }
  
          return result;
      }
  }, !reduceCoercesToObject);
  
  // ES5 15.4.4.22
  // http://es5.github.com/#x15.4.4.22
  // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight
  var reduceRightCoercesToObject = false;
  if (ArrayPrototype.reduceRight) {
      reduceRightCoercesToObject = typeof ArrayPrototype.reduceRight.call('es5', function (_, __, ___, list) { return list; }) === 'object';
  }
  defineProperties(ArrayPrototype, {
      reduceRight: function reduceRight(callbackfn/*, initial*/) {
          var object = ES.ToObject(this);
          var self = splitString && isString(this) ? strSplit(this, '') : object;
          var length = self.length >>> 0;
  
          // If no callback function or if callback is not a callable function
          if (!isCallable(callbackfn)) {
              throw new TypeError('Array.prototype.reduceRight callback must be a function');
          }
  
          // no value to return if no initial value, empty array
          if (length === 0 && arguments.length === 1) {
              throw new TypeError('reduceRight of empty array with no initial value');
          }
  
          var result;
          var i = length - 1;
          if (arguments.length >= 2) {
              result = arguments[1];
          } else {
              do {
                  if (i in self) {
                      result = self[i--];
                      break;
                  }
  
                  // if array contains no values, no initial value to return
                  if (--i < 0) {
                      throw new TypeError('reduceRight of empty array with no initial value');
                  }
              } while (true);
          }
  
          if (i < 0) {
              return result;
          }
  
          do {
              if (i in self) {
                  result = callbackfn(result, self[i], i, object);
              }
          } while (i--);
  
          return result;
      }
  }, !reduceRightCoercesToObject);
  
  // ES5 15.4.4.14
  // http://es5.github.com/#x15.4.4.14
  // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
  var hasFirefox2IndexOfBug = ArrayPrototype.indexOf && [0, 1].indexOf(1, 2) !== -1;
  defineProperties(ArrayPrototype, {
      indexOf: function indexOf(searchElement /*, fromIndex */) {
          var self = splitString && isString(this) ? strSplit(this, '') : ES.ToObject(this);
          var length = self.length >>> 0;
  
          if (length === 0) {
              return -1;
          }
  
          var i = 0;
          if (arguments.length > 1) {
              i = ES.ToInteger(arguments[1]);
          }
  
          // handle negative indices
          i = i >= 0 ? i : max(0, length + i);
          for (; i < length; i++) {
              if (i in self && self[i] === searchElement) {
                  return i;
              }
          }
          return -1;
      }
  }, hasFirefox2IndexOfBug);
  
  // ES5 15.4.4.15
  // http://es5.github.com/#x15.4.4.15
  // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf
  var hasFirefox2LastIndexOfBug = ArrayPrototype.lastIndexOf && [0, 1].lastIndexOf(0, -3) !== -1;
  defineProperties(ArrayPrototype, {
      lastIndexOf: function lastIndexOf(searchElement /*, fromIndex */) {
          var self = splitString && isString(this) ? strSplit(this, '') : ES.ToObject(this);
          var length = self.length >>> 0;
  
          if (length === 0) {
              return -1;
          }
          var i = length - 1;
          if (arguments.length > 1) {
              i = min(i, ES.ToInteger(arguments[1]));
          }
          // handle negative indices
          i = i >= 0 ? i : length - Math.abs(i);
          for (; i >= 0; i--) {
              if (i in self && searchElement === self[i]) {
                  return i;
              }
          }
          return -1;
      }
  }, hasFirefox2LastIndexOfBug);
  
  // ES5 15.4.4.12
  // http://es5.github.com/#x15.4.4.12
  var spliceNoopReturnsEmptyArray = (function () {
      var a = [1, 2];
      var result = a.splice();
      return a.length === 2 && isArray(result) && result.length === 0;
  }());
  defineProperties(ArrayPrototype, {
      // Safari 5.0 bug where .splice() returns undefined
      splice: function splice(start, deleteCount) {
          if (arguments.length === 0) {
              return [];
          } else {
              return array_splice.apply(this, arguments);
          }
      }
  }, !spliceNoopReturnsEmptyArray);
  
  var spliceWorksWithEmptyObject = (function () {
      var obj = {};
      ArrayPrototype.splice.call(obj, 0, 0, 1);
      return obj.length === 1;
  }());
  defineProperties(ArrayPrototype, {
      splice: function splice(start, deleteCount) {
          if (arguments.length === 0) { return []; }
          var args = arguments;
          this.length = max(ES.ToInteger(this.length), 0);
          if (arguments.length > 0 && typeof deleteCount !== 'number') {
              args = array_slice.call(arguments);
              if (args.length < 2) {
                  array_push.call(args, this.length - start);
              } else {
                  args[1] = ES.ToInteger(deleteCount);
              }
          }
          return array_splice.apply(this, args);
      }
  }, !spliceWorksWithEmptyObject);
  var spliceWorksWithLargeSparseArrays = (function () {
      // Per https://github.com/es-shims/es5-shim/issues/295
      // Safari 7/8 breaks with sparse arrays of size 1e5 or greater
      var arr = new $Array(1e5);
      // note: the index MUST be 8 or larger or the test will false pass
      arr[8] = 'x';
      arr.splice(1, 1);
      // note: this test must be defined *after* the indexOf shim
      // per https://github.com/es-shims/es5-shim/issues/313
      return arr.indexOf('x') === 7;
  }());
  var spliceWorksWithSmallSparseArrays = (function () {
      // Per https://github.com/es-shims/es5-shim/issues/295
      // Opera 12.15 breaks on this, no idea why.
      var n = 256;
      var arr = [];
      arr[n] = 'a';
      arr.splice(n + 1, 0, 'b');
      return arr[n] === 'a';
  }());
  defineProperties(ArrayPrototype, {
      splice: function splice(start, deleteCount) {
          var O = ES.ToObject(this);
          var A = [];
          var len = ES.ToUint32(O.length);
          var relativeStart = ES.ToInteger(start);
          var actualStart = relativeStart < 0 ? max((len + relativeStart), 0) : min(relativeStart, len);
          var actualDeleteCount = min(max(ES.ToInteger(deleteCount), 0), len - actualStart);
  
          var k = 0;
          var from;
          while (k < actualDeleteCount) {
              from = $String(actualStart + k);
              if (owns(O, from)) {
                  A[k] = O[from];
              }
              k += 1;
          }
  
          var items = array_slice.call(arguments, 2);
          var itemCount = items.length;
          var to;
          if (itemCount < actualDeleteCount) {
              k = actualStart;
              while (k < (len - actualDeleteCount)) {
                  from = $String(k + actualDeleteCount);
                  to = $String(k + itemCount);
                  if (owns(O, from)) {
                      O[to] = O[from];
                  } else {
                      delete O[to];
                  }
                  k += 1;
              }
              k = len;
              while (k > (len - actualDeleteCount + itemCount)) {
                  delete O[k - 1];
                  k -= 1;
              }
          } else if (itemCount > actualDeleteCount) {
              k = len - actualDeleteCount;
              while (k > actualStart) {
                  from = $String(k + actualDeleteCount - 1);
                  to = $String(k + itemCount - 1);
                  if (owns(O, from)) {
                      O[to] = O[from];
                  } else {
                      delete O[to];
                  }
                  k -= 1;
              }
          }
          k = actualStart;
          for (var i = 0; i < items.length; ++i) {
              O[k] = items[i];
              k += 1;
          }
          O.length = len - actualDeleteCount + itemCount;
  
          return A;
      }
  }, !spliceWorksWithLargeSparseArrays || !spliceWorksWithSmallSparseArrays);
  
  //
  // Object
  // ======
  //
  
  // ES5 15.2.3.14
  // http://es5.github.com/#x15.2.3.14
  
  // http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation
  var hasDontEnumBug = !({ 'toString': null }).propertyIsEnumerable('toString');
  var hasProtoEnumBug = function () {}.propertyIsEnumerable('prototype');
  var hasStringEnumBug = !owns('x', '0');
  var equalsConstructorPrototype = function (o) {
      var ctor = o.constructor;
      return ctor && ctor.prototype === o;
  };
  var blacklistedKeys = {
      $window: true,
      $console: true,
      $parent: true,
      $self: true,
      $frames: true,
      $frameElement: true,
      $webkitIndexedDB: true,
      $webkitStorageInfo: true
  };
  var hasAutomationEqualityBug = (function () {
      /* globals window */
      if (typeof window === 'undefined') { return false; }
      for (var k in window) {
          if (!blacklistedKeys['$' + k] && owns(window, k) && window[k] !== null && typeof window[k] === 'object') {
              try {
                  equalsConstructorPrototype(window[k]);
              } catch (e) {
                  return true;
              }
          }
      }
      return false;
  }());
  var equalsConstructorPrototypeIfNotBuggy = function (object) {
      if (typeof window === 'undefined' || !hasAutomationEqualityBug) { return equalsConstructorPrototype(object); }
      try {
          return equalsConstructorPrototype(object);
      } catch (e) {
          return false;
      }
  };
  var dontEnums = [
      'toString',
      'toLocaleString',
      'valueOf',
      'hasOwnProperty',
      'isPrototypeOf',
      'propertyIsEnumerable',
      'constructor'
  ];
  var dontEnumsLength = dontEnums.length;
  
  // taken directly from https://github.com/ljharb/is-arguments/blob/master/index.js
  // can be replaced with require('is-arguments') if we ever use a build process instead
  var isStandardArguments = function isArguments(value) {
      return toStr(value) === '[object Arguments]';
  };
  var isLegacyArguments = function isArguments(value) {
      return value !== null &&
          typeof value === 'object' &&
          typeof value.length === 'number' &&
          value.length >= 0 &&
          !isArray(value) &&
          isCallable(value.callee);
  };
  var isArguments = isStandardArguments(arguments) ? isStandardArguments : isLegacyArguments;
  
  defineProperties($Object, {
      keys: function keys(object) {
          var isFn = isCallable(object);
          var isArgs = isArguments(object);
          var isObject = object !== null && typeof object === 'object';
          var isStr = isObject && isString(object);
  
          if (!isObject && !isFn && !isArgs) {
              throw new TypeError('Object.keys called on a non-object');
          }
  
          var theKeys = [];
          var skipProto = hasProtoEnumBug && isFn;
          if ((isStr && hasStringEnumBug) || isArgs) {
              for (var i = 0; i < object.length; ++i) {
                  array_push.call(theKeys, $String(i));
              }
          }
  
          if (!isArgs) {
              for (var name in object) {
                  if (!(skipProto && name === 'prototype') && owns(object, name)) {
                      array_push.call(theKeys, $String(name));
                  }
              }
          }
  
          if (hasDontEnumBug) {
              var skipConstructor = equalsConstructorPrototypeIfNotBuggy(object);
              for (var j = 0; j < dontEnumsLength; j++) {
                  var dontEnum = dontEnums[j];
                  if (!(skipConstructor && dontEnum === 'constructor') && owns(object, dontEnum)) {
                      array_push.call(theKeys, dontEnum);
                  }
              }
          }
          return theKeys;
      }
  });
  
  var keysWorksWithArguments = $Object.keys && (function () {
      // Safari 5.0 bug
      return $Object.keys(arguments).length === 2;
  }(1, 2));
  var keysHasArgumentsLengthBug = $Object.keys && (function () {
      var argKeys = $Object.keys(arguments);
  	return arguments.length !== 1 || argKeys.length !== 1 || argKeys[0] !== 1;
  }(1));
  var originalKeys = $Object.keys;
  defineProperties($Object, {
      keys: function keys(object) {
          if (isArguments(object)) {
              return originalKeys(array_slice.call(object));
          } else {
              return originalKeys(object);
          }
      }
  }, !keysWorksWithArguments || keysHasArgumentsLengthBug);
  
  //
  // Date
  // ====
  //
  
  // ES5 15.9.5.43
  // http://es5.github.com/#x15.9.5.43
  // This function returns a String value represent the instance in time
  // represented by this Date object. The format of the String is the Date Time
  // string format defined in 15.9.1.15. All fields are present in the String.
  // The time zone is always UTC, denoted by the suffix Z. If the time value of
  // this object is not a finite Number a RangeError exception is thrown.
  var negativeDate = -62198755200000;
  var negativeYearString = '-000001';
  var hasNegativeDateBug = Date.prototype.toISOString && new Date(negativeDate).toISOString().indexOf(negativeYearString) === -1;
  var hasSafari51DateBug = Date.prototype.toISOString && new Date(-1).toISOString() !== '1969-12-31T23:59:59.999Z';
  
  defineProperties(Date.prototype, {
      toISOString: function toISOString() {
          var result, length, value, year, month;
          if (!isFinite(this)) {
              throw new RangeError('Date.prototype.toISOString called on non-finite value.');
          }
  
          year = this.getUTCFullYear();
  
          month = this.getUTCMonth();
          // see https://github.com/es-shims/es5-shim/issues/111
          year += Math.floor(month / 12);
          month = (month % 12 + 12) % 12;
  
          // the date time string format is specified in 15.9.1.15.
          result = [month + 1, this.getUTCDate(), this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds()];
          year = (
              (year < 0 ? '-' : (year > 9999 ? '+' : '')) +
              strSlice('00000' + Math.abs(year), (0 <= year && year <= 9999) ? -4 : -6)
          );
  
          length = result.length;
          while (length--) {
              value = result[length];
              // pad months, days, hours, minutes, and seconds to have two
              // digits.
              if (value < 10) {
                  result[length] = '0' + value;
              }
          }
          // pad milliseconds to have three digits.
          return (
              year + '-' + array_slice.call(result, 0, 2).join('-') +
              'T' + array_slice.call(result, 2).join(':') + '.' +
              strSlice('000' + this.getUTCMilliseconds(), -3) + 'Z'
          );
      }
  }, hasNegativeDateBug || hasSafari51DateBug);
  
  // ES5 15.9.5.44
  // http://es5.github.com/#x15.9.5.44
  // This function provides a String representation of a Date object for use by
  // JSON.stringify (15.12.3).
  var dateToJSONIsSupported = (function () {
      try {
          return Date.prototype.toJSON &&
              new Date(NaN).toJSON() === null &&
              new Date(negativeDate).toJSON().indexOf(negativeYearString) !== -1 &&
              Date.prototype.toJSON.call({ // generic
                  toISOString: function () { return true; }
              });
      } catch (e) {
          return false;
      }
  }());
  if (!dateToJSONIsSupported) {
      Date.prototype.toJSON = function toJSON(key) {
          // When the toJSON method is called with argument key, the following
          // steps are taken:
  
          // 1.  Let O be the result of calling ToObject, giving it the this
          // value as its argument.
          // 2. Let tv be ES.ToPrimitive(O, hint Number).
          var O = $Object(this);
          var tv = ES.ToPrimitive(O);
          // 3. If tv is a Number and is not finite, return null.
          if (typeof tv === 'number' && !isFinite(tv)) {
              return null;
          }
          // 4. Let toISO be the result of calling the [[Get]] internal method of
          // O with argument "toISOString".
          var toISO = O.toISOString;
          // 5. If IsCallable(toISO) is false, throw a TypeError exception.
          if (!isCallable(toISO)) {
              throw new TypeError('toISOString property is not callable');
          }
          // 6. Return the result of calling the [[Call]] internal method of
          //  toISO with O as the this value and an empty argument list.
          return toISO.call(O);
  
          // NOTE 1 The argument is ignored.
  
          // NOTE 2 The toJSON function is intentionally generic; it does not
          // require that its this value be a Date object. Therefore, it can be
          // transferred to other kinds of objects for use as a method. However,
          // it does require that any such object have a toISOString method. An
          // object is free to use the argument key to filter its
          // stringification.
      };
  }
  
  // ES5 15.9.4.2
  // http://es5.github.com/#x15.9.4.2
  // based on work shared by Daniel Friesen (dantman)
  // http://gist.github.com/303249
  var supportsExtendedYears = Date.parse('+033658-09-27T01:46:40.000Z') === 1e15;
  var acceptsInvalidDates = !isNaN(Date.parse('2012-04-04T24:00:00.500Z')) || !isNaN(Date.parse('2012-11-31T23:59:59.000Z')) || !isNaN(Date.parse('2012-12-31T23:59:60.000Z'));
  var doesNotParseY2KNewYear = isNaN(Date.parse('2000-01-01T00:00:00.000Z'));
  if (doesNotParseY2KNewYear || acceptsInvalidDates || !supportsExtendedYears) {
      // XXX global assignment won't work in embeddings that use
      // an alternate object for the context.
      /* global Date: true */
      /* eslint-disable no-undef */
      Date = (function (NativeDate) {
      /* eslint-enable no-undef */
          // Date.length === 7
          var DateShim = function Date(Y, M, D, h, m, s, ms) {
              var length = arguments.length;
              var date;
              if (this instanceof NativeDate) {
                  date = length === 1 && $String(Y) === Y ? // isString(Y)
                      // We explicitly pass it through parse:
                      new NativeDate(DateShim.parse(Y)) :
                      // We have to manually make calls depending on argument
                      // length here
                      length >= 7 ? new NativeDate(Y, M, D, h, m, s, ms) :
                      length >= 6 ? new NativeDate(Y, M, D, h, m, s) :
                      length >= 5 ? new NativeDate(Y, M, D, h, m) :
                      length >= 4 ? new NativeDate(Y, M, D, h) :
                      length >= 3 ? new NativeDate(Y, M, D) :
                      length >= 2 ? new NativeDate(Y, M) :
                      length >= 1 ? new NativeDate(Y) :
                                    new NativeDate();
              } else {
                  date = NativeDate.apply(this, arguments);
              }
              if (!isPrimitive(date)) {
                // Prevent mixups with unfixed Date object
                defineProperties(date, { constructor: DateShim }, true);
              }
              return date;
          };
  
          // 15.9.1.15 Date Time String Format.
          var isoDateExpression = new RegExp('^' +
              '(\\d{4}|[+-]\\d{6})' + // four-digit year capture or sign +
                                        // 6-digit extended year
              '(?:-(\\d{2})' + // optional month capture
              '(?:-(\\d{2})' + // optional day capture
              '(?:' + // capture hours:minutes:seconds.milliseconds
                  'T(\\d{2})' + // hours capture
                  ':(\\d{2})' + // minutes capture
                  '(?:' + // optional :seconds.milliseconds
                      ':(\\d{2})' + // seconds capture
                      '(?:(\\.\\d{1,}))?' + // milliseconds capture
                  ')?' +
              '(' + // capture UTC offset component
                  'Z|' + // UTC capture
                  '(?:' + // offset specifier +/-hours:minutes
                      '([-+])' + // sign capture
                      '(\\d{2})' + // hours offset capture
                      ':(\\d{2})' + // minutes offset capture
                  ')' +
              ')?)?)?)?' +
          '$');
  
          var months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365];
  
          var dayFromMonth = function dayFromMonth(year, month) {
              var t = month > 1 ? 1 : 0;
              return (
                  months[month] +
                  Math.floor((year - 1969 + t) / 4) -
                  Math.floor((year - 1901 + t) / 100) +
                  Math.floor((year - 1601 + t) / 400) +
                  365 * (year - 1970)
              );
          };
  
          var toUTC = function toUTC(t) {
              return $Number(new NativeDate(1970, 0, 1, 0, 0, 0, t));
          };
  
          // Copy any custom methods a 3rd party library may have added
          for (var key in NativeDate) {
              if (owns(NativeDate, key)) {
                  DateShim[key] = NativeDate[key];
              }
          }
  
          // Copy "native" methods explicitly; they may be non-enumerable
          defineProperties(DateShim, {
              now: NativeDate.now,
              UTC: NativeDate.UTC
          }, true);
          DateShim.prototype = NativeDate.prototype;
          defineProperties(DateShim.prototype, {
              constructor: DateShim
          }, true);
  
          // Upgrade Date.parse to handle simplified ISO 8601 strings
          var parseShim = function parse(string) {
              var match = isoDateExpression.exec(string);
              if (match) {
                  // parse months, days, hours, minutes, seconds, and milliseconds
                  // provide default values if necessary
                  // parse the UTC offset component
                  var year = $Number(match[1]),
                      month = $Number(match[2] || 1) - 1,
                      day = $Number(match[3] || 1) - 1,
                      hour = $Number(match[4] || 0),
                      minute = $Number(match[5] || 0),
                      second = $Number(match[6] || 0),
                      millisecond = Math.floor($Number(match[7] || 0) * 1000),
                      // When time zone is missed, local offset should be used
                      // (ES 5.1 bug)
                      // see https://bugs.ecmascript.org/show_bug.cgi?id=112
                      isLocalTime = Boolean(match[4] && !match[8]),
                      signOffset = match[9] === '-' ? 1 : -1,
                      hourOffset = $Number(match[10] || 0),
                      minuteOffset = $Number(match[11] || 0),
                      result;
                  if (
                      hour < (
                          minute > 0 || second > 0 || millisecond > 0 ?
                          24 : 25
                      ) &&
                      minute < 60 && second < 60 && millisecond < 1000 &&
                      month > -1 && month < 12 && hourOffset < 24 &&
                      minuteOffset < 60 && // detect invalid offsets
                      day > -1 &&
                      day < (
                          dayFromMonth(year, month + 1) -
                          dayFromMonth(year, month)
                      )
                  ) {
                      result = (
                          (dayFromMonth(year, month) + day) * 24 +
                          hour +
                          hourOffset * signOffset
                      ) * 60;
                      result = (
                          (result + minute + minuteOffset * signOffset) * 60 +
                          second
                      ) * 1000 + millisecond;
                      if (isLocalTime) {
                          result = toUTC(result);
                      }
                      if (-8.64e15 <= result && result <= 8.64e15) {
                          return result;
                      }
                  }
                  return NaN;
              }
              return NativeDate.parse.apply(this, arguments);
          };
          defineProperties(DateShim, { parse: parseShim });
  
          return DateShim;
      }(Date));
      /* global Date: false */
  }
  
  // ES5 15.9.4.4
  // http://es5.github.com/#x15.9.4.4
  if (!Date.now) {
      Date.now = function now() {
          return new Date().getTime();
      };
  }
  
  //
  // Number
  // ======
  //
  
  // ES5.1 15.7.4.5
  // http://es5.github.com/#x15.7.4.5
  var hasToFixedBugs = NumberPrototype.toFixed && (
    (0.00008).toFixed(3) !== '0.000' ||
    (0.9).toFixed(0) !== '1' ||
    (1.255).toFixed(2) !== '1.25' ||
    (1000000000000000128).toFixed(0) !== '1000000000000000128'
  );
  
  var toFixedHelpers = {
    base: 1e7,
    size: 6,
    data: [0, 0, 0, 0, 0, 0],
    multiply: function multiply(n, c) {
        var i = -1;
        var c2 = c;
        while (++i < toFixedHelpers.size) {
            c2 += n * toFixedHelpers.data[i];
            toFixedHelpers.data[i] = c2 % toFixedHelpers.base;
            c2 = Math.floor(c2 / toFixedHelpers.base);
        }
    },
    divide: function divide(n) {
        var i = toFixedHelpers.size, c = 0;
        while (--i >= 0) {
            c += toFixedHelpers.data[i];
            toFixedHelpers.data[i] = Math.floor(c / n);
            c = (c % n) * toFixedHelpers.base;
        }
    },
    numToString: function numToString() {
        var i = toFixedHelpers.size;
        var s = '';
        while (--i >= 0) {
            if (s !== '' || i === 0 || toFixedHelpers.data[i] !== 0) {
                var t = $String(toFixedHelpers.data[i]);
                if (s === '') {
                    s = t;
                } else {
                    s += strSlice('0000000', 0, 7 - t.length) + t;
                }
            }
        }
        return s;
    },
    pow: function pow(x, n, acc) {
        return (n === 0 ? acc : (n % 2 === 1 ? pow(x, n - 1, acc * x) : pow(x * x, n / 2, acc)));
    },
    log: function log(x) {
        var n = 0;
        var x2 = x;
        while (x2 >= 4096) {
            n += 12;
            x2 /= 4096;
        }
        while (x2 >= 2) {
            n += 1;
            x2 /= 2;
        }
        return n;
    }
  };
  
  defineProperties(NumberPrototype, {
      toFixed: function toFixed(fractionDigits) {
          var f, x, s, m, e, z, j, k;
  
          // Test for NaN and round fractionDigits down
          f = $Number(fractionDigits);
          f = f !== f ? 0 : Math.floor(f);
  
          if (f < 0 || f > 20) {
              throw new RangeError('Number.toFixed called with invalid number of decimals');
          }
  
          x = $Number(this);
  
          // Test for NaN
          if (x !== x) {
              return 'NaN';
          }
  
          // If it is too big or small, return the string value of the number
          if (x <= -1e21 || x >= 1e21) {
              return $String(x);
          }
  
          s = '';
  
          if (x < 0) {
              s = '-';
              x = -x;
          }
  
          m = '0';
  
          if (x > 1e-21) {
              // 1e-21 < x < 1e21
              // -70 < log2(x) < 70
              e = toFixedHelpers.log(x * toFixedHelpers.pow(2, 69, 1)) - 69;
              z = (e < 0 ? x * toFixedHelpers.pow(2, -e, 1) : x / toFixedHelpers.pow(2, e, 1));
              z *= 0x10000000000000; // Math.pow(2, 52);
              e = 52 - e;
  
              // -18 < e < 122
              // x = z / 2 ^ e
              if (e > 0) {
                  toFixedHelpers.multiply(0, z);
                  j = f;
  
                  while (j >= 7) {
                      toFixedHelpers.multiply(1e7, 0);
                      j -= 7;
                  }
  
                  toFixedHelpers.multiply(toFixedHelpers.pow(10, j, 1), 0);
                  j = e - 1;
  
                  while (j >= 23) {
                      toFixedHelpers.divide(1 << 23);
                      j -= 23;
                  }
  
                  toFixedHelpers.divide(1 << j);
                  toFixedHelpers.multiply(1, 1);
                  toFixedHelpers.divide(2);
                  m = toFixedHelpers.numToString();
              } else {
                  toFixedHelpers.multiply(0, z);
                  toFixedHelpers.multiply(1 << (-e), 0);
                  m = toFixedHelpers.numToString() + strSlice('0.00000000000000000000', 2, 2 + f);
              }
          }
  
          if (f > 0) {
              k = m.length;
  
              if (k <= f) {
                  m = s + strSlice('0.0000000000000000000', 0, f - k + 2) + m;
              } else {
                  m = s + strSlice(m, 0, k - f) + '.' + strSlice(m, k - f);
              }
          } else {
              m = s + m;
          }
  
          return m;
      }
  }, hasToFixedBugs);
  
  //
  // String
  // ======
  //
  
  // ES5 15.5.4.14
  // http://es5.github.com/#x15.5.4.14
  
  // [bugfix, IE lt 9, firefox 4, Konqueror, Opera, obscure browsers]
  // Many browsers do not split properly with regular expressions or they
  // do not perform the split correctly under obscure conditions.
  // See http://blog.stevenlevithan.com/archives/cross-browser-split
  // I've tested in many browsers and this seems to cover the deviant ones:
  //    'ab'.split(/(?:ab)*/) should be ["", ""], not [""]
  //    '.'.split(/(.?)(.?)/) should be ["", ".", "", ""], not ["", ""]
  //    'tesst'.split(/(s)*/) should be ["t", undefined, "e", "s", "t"], not
  //       [undefined, "t", undefined, "e", ...]
  //    ''.split(/.?/) should be [], not [""]
  //    '.'.split(/()()/) should be ["."], not ["", "", "."]
  
  if (
      'ab'.split(/(?:ab)*/).length !== 2 ||
      '.'.split(/(.?)(.?)/).length !== 4 ||
      'tesst'.split(/(s)*/)[1] === 't' ||
      'test'.split(/(?:)/, -1).length !== 4 ||
      ''.split(/.?/).length ||
      '.'.split(/()()/).length > 1
  ) {
      (function () {
          var compliantExecNpcg = typeof (/()??/).exec('')[1] === 'undefined'; // NPCG: nonparticipating capturing group
  
          StringPrototype.split = function (separator, limit) {
              var string = this;
              if (typeof separator === 'undefined' && limit === 0) {
                  return [];
              }
  
              // If `separator` is not a regex, use native split
              if (!isRegex(separator)) {
                  return strSplit(this, separator, limit);
              }
  
              var output = [];
              var flags = (separator.ignoreCase ? 'i' : '') +
                          (separator.multiline ? 'm' : '') +
                          (separator.unicode ? 'u' : '') + // in ES6
                          (separator.sticky ? 'y' : ''), // Firefox 3+ and ES6
                  lastLastIndex = 0,
                  // Make `global` and avoid `lastIndex` issues by working with a copy
                  separator2, match, lastIndex, lastLength;
              var separatorCopy = new RegExp(separator.source, flags + 'g');
              string += ''; // Type-convert
              if (!compliantExecNpcg) {
                  // Doesn't need flags gy, but they don't hurt
                  separator2 = new RegExp('^' + separatorCopy.source + '$(?!\\s)', flags);
              }
              /* Values for `limit`, per the spec:
               * If undefined: 4294967295 // Math.pow(2, 32) - 1
               * If 0, Infinity, or NaN: 0
               * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
               * If negative number: 4294967296 - Math.floor(Math.abs(limit))
               * If other: Type-convert, then use the above rules
               */
              var splitLimit = typeof limit === 'undefined' ?
                  -1 >>> 0 : // Math.pow(2, 32) - 1
                  ES.ToUint32(limit);
              match = separatorCopy.exec(string);
              while (match) {
                  // `separatorCopy.lastIndex` is not reliable cross-browser
                  lastIndex = match.index + match[0].length;
                  if (lastIndex > lastLastIndex) {
                      array_push.call(output, strSlice(string, lastLastIndex, match.index));
                      // Fix browsers whose `exec` methods don't consistently return `undefined` for
                      // nonparticipating capturing groups
                      if (!compliantExecNpcg && match.length > 1) {
                          /* eslint-disable no-loop-func */
                          match[0].replace(separator2, function () {
                              for (var i = 1; i < arguments.length - 2; i++) {
                                  if (typeof arguments[i] === 'undefined') {
                                      match[i] = void 0;
                                  }
                              }
                          });
                          /* eslint-enable no-loop-func */
                      }
                      if (match.length > 1 && match.index < string.length) {
                          array_push.apply(output, array_slice.call(match, 1));
                      }
                      lastLength = match[0].length;
                      lastLastIndex = lastIndex;
                      if (output.length >= splitLimit) {
                          break;
                      }
                  }
                  if (separatorCopy.lastIndex === match.index) {
                      separatorCopy.lastIndex++; // Avoid an infinite loop
                  }
                  match = separatorCopy.exec(string);
              }
              if (lastLastIndex === string.length) {
                  if (lastLength || !separatorCopy.test('')) {
                      array_push.call(output, '');
                  }
              } else {
                  array_push.call(output, strSlice(string, lastLastIndex));
              }
              return output.length > splitLimit ? strSlice(output, 0, splitLimit) : output;
          };
      }());
  
  // [bugfix, chrome]
  // If separator is undefined, then the result array contains just one String,
  // which is the this value (converted to a String). If limit is not undefined,
  // then the output array is truncated so that it contains no more than limit
  // elements.
  // "0".split(undefined, 0) -> []
  } else if ('0'.split(void 0, 0).length) {
      StringPrototype.split = function split(separator, limit) {
          if (typeof separator === 'undefined' && limit === 0) { return []; }
          return strSplit(this, separator, limit);
      };
  }
  
  var str_replace = StringPrototype.replace;
  var replaceReportsGroupsCorrectly = (function () {
      var groups = [];
      'x'.replace(/x(.)?/g, function (match, group) {
          array_push.call(groups, group);
      });
      return groups.length === 1 && typeof groups[0] === 'undefined';
  }());
  
  if (!replaceReportsGroupsCorrectly) {
      StringPrototype.replace = function replace(searchValue, replaceValue) {
          var isFn = isCallable(replaceValue);
          var hasCapturingGroups = isRegex(searchValue) && (/\)[*?]/).test(searchValue.source);
          if (!isFn || !hasCapturingGroups) {
              return str_replace.call(this, searchValue, replaceValue);
          } else {
              var wrappedReplaceValue = function (match) {
                  var length = arguments.length;
                  var originalLastIndex = searchValue.lastIndex;
                  searchValue.lastIndex = 0;
                  var args = searchValue.exec(match) || [];
                  searchValue.lastIndex = originalLastIndex;
                  array_push.call(args, arguments[length - 2], arguments[length - 1]);
                  return replaceValue.apply(this, args);
              };
              return str_replace.call(this, searchValue, wrappedReplaceValue);
          }
      };
  }
  
  // ECMA-262, 3rd B.2.3
  // Not an ECMAScript standard, although ECMAScript 3rd Edition has a
  // non-normative section suggesting uniform semantics and it should be
  // normalized across all browsers
  // [bugfix, IE lt 9] IE < 9 substr() with negative value not working in IE
  var string_substr = StringPrototype.substr;
  var hasNegativeSubstrBug = ''.substr && '0b'.substr(-1) !== 'b';
  defineProperties(StringPrototype, {
      substr: function substr(start, length) {
          var normalizedStart = start;
          if (start < 0) {
              normalizedStart = max(this.length + start, 0);
          }
          return string_substr.call(this, normalizedStart, length);
      }
  }, hasNegativeSubstrBug);
  
  // ES5 15.5.4.20
  // whitespace from: http://es5.github.io/#x15.5.4.20
  var ws = '\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003' +
      '\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028' +
      '\u2029\uFEFF';
  var zeroWidth = '\u200b';
  var wsRegexChars = '[' + ws + ']';
  var trimBeginRegexp = new RegExp('^' + wsRegexChars + wsRegexChars + '*');
  var trimEndRegexp = new RegExp(wsRegexChars + wsRegexChars + '*$');
  var hasTrimWhitespaceBug = StringPrototype.trim && (ws.trim() || !zeroWidth.trim());
  defineProperties(StringPrototype, {
      // http://blog.stevenlevithan.com/archives/faster-trim-javascript
      // http://perfectionkills.com/whitespace-deviations/
      trim: function trim() {
          if (typeof this === 'undefined' || this === null) {
              throw new TypeError("can't convert " + this + ' to object');
          }
          return $String(this).replace(trimBeginRegexp, '').replace(trimEndRegexp, '');
      }
  }, hasTrimWhitespaceBug);
  
  // ES-5 15.1.2.2
  if (parseInt(ws + '08') !== 8 || parseInt(ws + '0x16') !== 22) {
      /* global parseInt: true */
      parseInt = (function (origParseInt) {
          var hexRegex = /^0[xX]/;
          return function parseInt(str, radix) {
              var string = $String(str).trim();
              var defaultedRadix = $Number(radix) || (hexRegex.test(string) ? 16 : 10);
              return origParseInt(string, defaultedRadix);
          };
      }(parseInt));
  }
  
  }));
  
  /*! JSON v3.3.2 | http://bestiejs.github.io/json3 | Copyright 2012-2014, Kit Cambridge | http://kit.mit-license.org */
  (function(){function N(p,r){function q(a){if(q[a]!==w)return q[a];var c;if("bug-string-char-index"==a)c="a"!="a"[0];else if("json"==a)c=q("json-stringify")&&q("json-parse");else{var e;if("json-stringify"==a){c=r.stringify;var b="function"==typeof c&&s;if(b){(e=function(){return 1}).toJSON=e;try{b="0"===c(0)&&"0"===c(new t)&&'""'==c(new A)&&c(u)===w&&c(w)===w&&c()===w&&"1"===c(e)&&"[1]"==c([e])&&"[null]"==c([w])&&"null"==c(null)&&"[null,null,null]"==c([w,u,null])&&'{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}'==
  c({a:[e,!0,!1,null,"\x00\b\n\f\r\t"]})&&"1"===c(null,e)&&"[\n 1,\n 2\n]"==c([1,2],null,1)&&'"-271821-04-20T00:00:00.000Z"'==c(new C(-864E13))&&'"+275760-09-13T00:00:00.000Z"'==c(new C(864E13))&&'"-000001-01-01T00:00:00.000Z"'==c(new C(-621987552E5))&&'"1969-12-31T23:59:59.999Z"'==c(new C(-1))}catch(f){b=!1}}c=b}if("json-parse"==a){c=r.parse;if("function"==typeof c)try{if(0===c("0")&&!c(!1)){e=c('{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}');var n=5==e.a.length&&1===e.a[0];if(n){try{n=!c('"\t"')}catch(d){}if(n)try{n=
  1!==c("01")}catch(g){}if(n)try{n=1!==c("1.")}catch(m){}}}}catch(X){n=!1}c=n}}return q[a]=!!c}p||(p=k.Object());r||(r=k.Object());var t=p.Number||k.Number,A=p.String||k.String,H=p.Object||k.Object,C=p.Date||k.Date,G=p.SyntaxError||k.SyntaxError,K=p.TypeError||k.TypeError,L=p.Math||k.Math,I=p.JSON||k.JSON;"object"==typeof I&&I&&(r.stringify=I.stringify,r.parse=I.parse);var H=H.prototype,u=H.toString,v,B,w,s=new C(-0xc782b5b800cec);try{s=-109252==s.getUTCFullYear()&&0===s.getUTCMonth()&&1===s.getUTCDate()&&
  10==s.getUTCHours()&&37==s.getUTCMinutes()&&6==s.getUTCSeconds()&&708==s.getUTCMilliseconds()}catch(Q){}if(!q("json")){var D=q("bug-string-char-index");if(!s)var x=L.floor,M=[0,31,59,90,120,151,181,212,243,273,304,334],E=function(a,c){return M[c]+365*(a-1970)+x((a-1969+(c=+(1<c)))/4)-x((a-1901+c)/100)+x((a-1601+c)/400)};(v=H.hasOwnProperty)||(v=function(a){var c={},e;(c.__proto__=null,c.__proto__={toString:1},c).toString!=u?v=function(a){var c=this.__proto__;a=a in(this.__proto__=null,this);this.__proto__=
  c;return a}:(e=c.constructor,v=function(a){var c=(this.constructor||e).prototype;return a in this&&!(a in c&&this[a]===c[a])});c=null;return v.call(this,a)});B=function(a,c){var e=0,b,f,n;(b=function(){this.valueOf=0}).prototype.valueOf=0;f=new b;for(n in f)v.call(f,n)&&e++;b=f=null;e?B=2==e?function(a,c){var e={},b="[object Function]"==u.call(a),f;for(f in a)b&&"prototype"==f||v.call(e,f)||!(e[f]=1)||!v.call(a,f)||c(f)}:function(a,c){var e="[object Function]"==u.call(a),b,f;for(b in a)e&&"prototype"==
  b||!v.call(a,b)||(f="constructor"===b)||c(b);(f||v.call(a,b="constructor"))&&c(b)}:(f="valueOf toString toLocaleString propertyIsEnumerable isPrototypeOf hasOwnProperty constructor".split(" "),B=function(a,c){var e="[object Function]"==u.call(a),b,h=!e&&"function"!=typeof a.constructor&&F[typeof a.hasOwnProperty]&&a.hasOwnProperty||v;for(b in a)e&&"prototype"==b||!h.call(a,b)||c(b);for(e=f.length;b=f[--e];h.call(a,b)&&c(b));});return B(a,c)};if(!q("json-stringify")){var U={92:"\\\\",34:'\\"',8:"\\b",
  12:"\\f",10:"\\n",13:"\\r",9:"\\t"},y=function(a,c){return("000000"+(c||0)).slice(-a)},R=function(a){for(var c='"',b=0,h=a.length,f=!D||10<h,n=f&&(D?a.split(""):a);b<h;b++){var d=a.charCodeAt(b);switch(d){case 8:case 9:case 10:case 12:case 13:case 34:case 92:c+=U[d];break;default:if(32>d){c+="\\u00"+y(2,d.toString(16));break}c+=f?n[b]:a.charAt(b)}}return c+'"'},O=function(a,c,b,h,f,n,d){var g,m,k,l,p,r,s,t,q;try{g=c[a]}catch(z){}if("object"==typeof g&&g)if(m=u.call(g),"[object Date]"!=m||v.call(g,
  "toJSON"))"function"==typeof g.toJSON&&("[object Number]"!=m&&"[object String]"!=m&&"[object Array]"!=m||v.call(g,"toJSON"))&&(g=g.toJSON(a));else if(g>-1/0&&g<1/0){if(E){l=x(g/864E5);for(m=x(l/365.2425)+1970-1;E(m+1,0)<=l;m++);for(k=x((l-E(m,0))/30.42);E(m,k+1)<=l;k++);l=1+l-E(m,k);p=(g%864E5+864E5)%864E5;r=x(p/36E5)%24;s=x(p/6E4)%60;t=x(p/1E3)%60;p%=1E3}else m=g.getUTCFullYear(),k=g.getUTCMonth(),l=g.getUTCDate(),r=g.getUTCHours(),s=g.getUTCMinutes(),t=g.getUTCSeconds(),p=g.getUTCMilliseconds();
  g=(0>=m||1E4<=m?(0>m?"-":"+")+y(6,0>m?-m:m):y(4,m))+"-"+y(2,k+1)+"-"+y(2,l)+"T"+y(2,r)+":"+y(2,s)+":"+y(2,t)+"."+y(3,p)+"Z"}else g=null;b&&(g=b.call(c,a,g));if(null===g)return"null";m=u.call(g);if("[object Boolean]"==m)return""+g;if("[object Number]"==m)return g>-1/0&&g<1/0?""+g:"null";if("[object String]"==m)return R(""+g);if("object"==typeof g){for(a=d.length;a--;)if(d[a]===g)throw K();d.push(g);q=[];c=n;n+=f;if("[object Array]"==m){k=0;for(a=g.length;k<a;k++)m=O(k,g,b,h,f,n,d),q.push(m===w?"null":
  m);a=q.length?f?"[\n"+n+q.join(",\n"+n)+"\n"+c+"]":"["+q.join(",")+"]":"[]"}else B(h||g,function(a){var c=O(a,g,b,h,f,n,d);c!==w&&q.push(R(a)+":"+(f?" ":"")+c)}),a=q.length?f?"{\n"+n+q.join(",\n"+n)+"\n"+c+"}":"{"+q.join(",")+"}":"{}";d.pop();return a}};r.stringify=function(a,c,b){var h,f,n,d;if(F[typeof c]&&c)if("[object Function]"==(d=u.call(c)))f=c;else if("[object Array]"==d){n={};for(var g=0,k=c.length,l;g<k;l=c[g++],(d=u.call(l),"[object String]"==d||"[object Number]"==d)&&(n[l]=1));}if(b)if("[object Number]"==
  (d=u.call(b))){if(0<(b-=b%1))for(h="",10<b&&(b=10);h.length<b;h+=" ");}else"[object String]"==d&&(h=10>=b.length?b:b.slice(0,10));return O("",(l={},l[""]=a,l),f,n,h,"",[])}}if(!q("json-parse")){var V=A.fromCharCode,W={92:"\\",34:'"',47:"/",98:"\b",116:"\t",110:"\n",102:"\f",114:"\r"},b,J,l=function(){b=J=null;throw G();},z=function(){for(var a=J,c=a.length,e,h,f,k,d;b<c;)switch(d=a.charCodeAt(b),d){case 9:case 10:case 13:case 32:b++;break;case 123:case 125:case 91:case 93:case 58:case 44:return e=
  D?a.charAt(b):a[b],b++,e;case 34:e="@";for(b++;b<c;)if(d=a.charCodeAt(b),32>d)l();else if(92==d)switch(d=a.charCodeAt(++b),d){case 92:case 34:case 47:case 98:case 116:case 110:case 102:case 114:e+=W[d];b++;break;case 117:h=++b;for(f=b+4;b<f;b++)d=a.charCodeAt(b),48<=d&&57>=d||97<=d&&102>=d||65<=d&&70>=d||l();e+=V("0x"+a.slice(h,b));break;default:l()}else{if(34==d)break;d=a.charCodeAt(b);for(h=b;32<=d&&92!=d&&34!=d;)d=a.charCodeAt(++b);e+=a.slice(h,b)}if(34==a.charCodeAt(b))return b++,e;l();default:h=
  b;45==d&&(k=!0,d=a.charCodeAt(++b));if(48<=d&&57>=d){for(48==d&&(d=a.charCodeAt(b+1),48<=d&&57>=d)&&l();b<c&&(d=a.charCodeAt(b),48<=d&&57>=d);b++);if(46==a.charCodeAt(b)){for(f=++b;f<c&&(d=a.charCodeAt(f),48<=d&&57>=d);f++);f==b&&l();b=f}d=a.charCodeAt(b);if(101==d||69==d){d=a.charCodeAt(++b);43!=d&&45!=d||b++;for(f=b;f<c&&(d=a.charCodeAt(f),48<=d&&57>=d);f++);f==b&&l();b=f}return+a.slice(h,b)}k&&l();if("true"==a.slice(b,b+4))return b+=4,!0;if("false"==a.slice(b,b+5))return b+=5,!1;if("null"==a.slice(b,
  b+4))return b+=4,null;l()}return"$"},P=function(a){var c,b;"$"==a&&l();if("string"==typeof a){if("@"==(D?a.charAt(0):a[0]))return a.slice(1);if("["==a){for(c=[];;b||(b=!0)){a=z();if("]"==a)break;b&&(","==a?(a=z(),"]"==a&&l()):l());","==a&&l();c.push(P(a))}return c}if("{"==a){for(c={};;b||(b=!0)){a=z();if("}"==a)break;b&&(","==a?(a=z(),"}"==a&&l()):l());","!=a&&"string"==typeof a&&"@"==(D?a.charAt(0):a[0])&&":"==z()||l();c[a.slice(1)]=P(z())}return c}l()}return a},T=function(a,b,e){e=S(a,b,e);e===
  w?delete a[b]:a[b]=e},S=function(a,b,e){var h=a[b],f;if("object"==typeof h&&h)if("[object Array]"==u.call(h))for(f=h.length;f--;)T(h,f,e);else B(h,function(a){T(h,a,e)});return e.call(a,b,h)};r.parse=function(a,c){var e,h;b=0;J=""+a;e=P(z());"$"!=z()&&l();b=J=null;return c&&"[object Function]"==u.call(c)?S((h={},h[""]=e,h),"",c):e}}}r.runInContext=N;return r}var K=typeof define==="function"&&define.amd,F={"function":!0,object:!0},G=F[typeof exports]&&exports&&!exports.nodeType&&exports,k=F[typeof window]&&
  window||this,t=G&&F[typeof module]&&module&&!module.nodeType&&"object"==typeof global&&global;!t||t.global!==t&&t.window!==t&&t.self!==t||(k=t);if(G&&!K)N(k,G);else{var L=k.JSON,Q=k.JSON3,M=!1,A=N(k,k.JSON3={noConflict:function(){M||(M=!0,k.JSON=L,k.JSON3=Q,L=Q=null);return A}});k.JSON={parse:A.parse,stringify:A.stringify}}K&&define(function(){return A})}).call(this);
  