[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/resources/lib/es5-shim/ -> es5-shim.js (source)

   1  /*!
   2   * https://github.com/es-shims/es5-shim
   3   * @license es5-shim Copyright 2009-2014 by contributors, MIT License
   4   * see https://github.com/es-shims/es5-shim/blob/master/LICENSE
   5   */
   6  
   7  // vim: ts=4 sts=4 sw=4 expandtab
   8  
   9  //Add semicolon to prevent IIFE from being passed as argument to concated code.
  10  ;
  11  
  12  // UMD (Universal Module Definition)
  13  // see https://github.com/umdjs/umd/blob/master/returnExports.js
  14  (function (root, factory) {
  15      if (typeof define === 'function' && define.amd) {
  16          // AMD. Register as an anonymous module.
  17          define(factory);
  18      } else if (typeof exports === 'object') {
  19          // Node. Does not work with strict CommonJS, but
  20          // only CommonJS-like enviroments that support module.exports,
  21          // like Node.
  22          module.exports = factory();
  23      } else {
  24          // Browser globals (root is window)
  25          root.returnExports = factory();
  26      }
  27  }(this, function () {
  28  
  29  /**
  30   * Brings an environment as close to ECMAScript 5 compliance
  31   * as is possible with the facilities of erstwhile engines.
  32   *
  33   * Annotated ES5: http://es5.github.com/ (specific links below)
  34   * ES5 Spec: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
  35   * Required reading: http://javascriptweblog.wordpress.com/2011/12/05/extending-javascript-natives/
  36   */
  37  
  38  // Shortcut to an often accessed properties, in order to avoid multiple
  39  // dereference that costs universally.
  40  var ArrayPrototype = Array.prototype;
  41  var ObjectPrototype = Object.prototype;
  42  var FunctionPrototype = Function.prototype;
  43  var StringPrototype = String.prototype;
  44  var NumberPrototype = Number.prototype;
  45  var _Array_slice_ = ArrayPrototype.slice;
  46  var array_splice = ArrayPrototype.splice;
  47  var array_push = ArrayPrototype.push;
  48  var array_unshift = ArrayPrototype.unshift;
  49  var call = FunctionPrototype.call;
  50  
  51  // Having a toString local variable name breaks in Opera so use _toString.
  52  var _toString = ObjectPrototype.toString;
  53  
  54  var isFunction = function (val) {
  55      return ObjectPrototype.toString.call(val) === '[object Function]';
  56  };
  57  var isRegex = function (val) {
  58      return ObjectPrototype.toString.call(val) === '[object RegExp]';
  59  };
  60  var isArray = function isArray(obj) {
  61      return _toString.call(obj) === "[object Array]";
  62  };
  63  var isString = function isString(obj) {
  64      return _toString.call(obj) === "[object String]";
  65  };
  66  var isArguments = function isArguments(value) {
  67      var str = _toString.call(value);
  68      var isArgs = str === '[object Arguments]';
  69      if (!isArgs) {
  70          isArgs = !isArray(str)
  71              && value !== null
  72              && typeof value === 'object'
  73              && typeof value.length === 'number'
  74              && value.length >= 0
  75              && isFunction(value.callee);
  76      }
  77      return isArgs;
  78  };
  79  
  80  var supportsDescriptors = Object.defineProperty && (function () {
  81      try {
  82          Object.defineProperty({}, 'x', {});
  83          return true;
  84      } catch (e) { /* this is ES3 */
  85          return false;
  86      }
  87  }());
  88  
  89  // Define configurable, writable and non-enumerable props
  90  // if they don't exist.
  91  var defineProperty;
  92  if (supportsDescriptors) {
  93      defineProperty = function (object, name, method, forceAssign) {
  94          if (!forceAssign && (name in object)) { return; }
  95          Object.defineProperty(object, name, {
  96              configurable: true,
  97              enumerable: false,
  98              writable: true,
  99              value: method
 100          });
 101      };
 102  } else {
 103      defineProperty = function (object, name, method, forceAssign) {
 104          if (!forceAssign && (name in object)) { return; }
 105          object[name] = method;
 106      };
 107  }
 108  var defineProperties = function (object, map, forceAssign) {
 109      for (var name in map) {
 110          if (ObjectPrototype.hasOwnProperty.call(map, name)) {
 111            defineProperty(object, name, map[name], forceAssign);
 112          }
 113      }
 114  };
 115  
 116  //
 117  // Util
 118  // ======
 119  //
 120  
 121  // ES5 9.4
 122  // http://es5.github.com/#x9.4
 123  // http://jsperf.com/to-integer
 124  
 125  function toInteger(n) {
 126      n = +n;
 127      if (n !== n) { // isNaN
 128          n = 0;
 129      } else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) {
 130          n = (n > 0 || -1) * Math.floor(Math.abs(n));
 131      }
 132      return n;
 133  }
 134  
 135  function isPrimitive(input) {
 136      var type = typeof input;
 137      return (
 138          input === null ||
 139          type === "undefined" ||
 140          type === "boolean" ||
 141          type === "number" ||
 142          type === "string"
 143      );
 144  }
 145  
 146  function toPrimitive(input) {
 147      var val, valueOf, toStr;
 148      if (isPrimitive(input)) {
 149          return input;
 150      }
 151      valueOf = input.valueOf;
 152      if (isFunction(valueOf)) {
 153          val = valueOf.call(input);
 154          if (isPrimitive(val)) {
 155              return val;
 156          }
 157      }
 158      toStr = input.toString;
 159      if (isFunction(toStr)) {
 160          val = toStr.call(input);
 161          if (isPrimitive(val)) {
 162              return val;
 163          }
 164      }
 165      throw new TypeError();
 166  }
 167  
 168  // ES5 9.9
 169  // http://es5.github.com/#x9.9
 170  var toObject = function (o) {
 171      if (o == null) { // this matches both null and undefined
 172          throw new TypeError("can't convert " + o + " to object");
 173      }
 174      return Object(o);
 175  };
 176  
 177  var ToUint32 = function ToUint32(x) {
 178      return x >>> 0;
 179  };
 180  
 181  //
 182  // Function
 183  // ========
 184  //
 185  
 186  // ES-5 15.3.4.5
 187  // http://es5.github.com/#x15.3.4.5
 188  
 189  function Empty() {}
 190  
 191  defineProperties(FunctionPrototype, {
 192      bind: function bind(that) { // .length is 1
 193          // 1. Let Target be the this value.
 194          var target = this;
 195          // 2. If IsCallable(Target) is false, throw a TypeError exception.
 196          if (!isFunction(target)) {
 197              throw new TypeError("Function.prototype.bind called on incompatible " + target);
 198          }
 199          // 3. Let A be a new (possibly empty) internal list of all of the
 200          //   argument values provided after thisArg (arg1, arg2 etc), in order.
 201          // XXX slicedArgs will stand in for "A" if used
 202          var args = _Array_slice_.call(arguments, 1); // for normal call
 203          // 4. Let F be a new native ECMAScript object.
 204          // 11. Set the [[Prototype]] internal property of F to the standard
 205          //   built-in Function prototype object as specified in 15.3.3.1.
 206          // 12. Set the [[Call]] internal property of F as described in
 207          //   15.3.4.5.1.
 208          // 13. Set the [[Construct]] internal property of F as described in
 209          //   15.3.4.5.2.
 210          // 14. Set the [[HasInstance]] internal property of F as described in
 211          //   15.3.4.5.3.
 212          var binder = function () {
 213  
 214              if (this instanceof bound) {
 215                  // 15.3.4.5.2 [[Construct]]
 216                  // When the [[Construct]] internal method of a function object,
 217                  // F that was created using the bind function is called with a
 218                  // list of arguments ExtraArgs, the following steps are taken:
 219                  // 1. Let target be the value of F's [[TargetFunction]]
 220                  //   internal property.
 221                  // 2. If target has no [[Construct]] internal method, a
 222                  //   TypeError exception is thrown.
 223                  // 3. Let boundArgs be the value of F's [[BoundArgs]] internal
 224                  //   property.
 225                  // 4. Let args be a new list containing the same values as the
 226                  //   list boundArgs in the same order followed by the same
 227                  //   values as the list ExtraArgs in the same order.
 228                  // 5. Return the result of calling the [[Construct]] internal
 229                  //   method of target providing args as the arguments.
 230  
 231                  var result = target.apply(
 232                      this,
 233                      args.concat(_Array_slice_.call(arguments))
 234                  );
 235                  if (Object(result) === result) {
 236                      return result;
 237                  }
 238                  return this;
 239  
 240              } else {
 241                  // 15.3.4.5.1 [[Call]]
 242                  // When the [[Call]] internal method of a function object, F,
 243                  // which was created using the bind function is called with a
 244                  // this value and a list of arguments ExtraArgs, the following
 245                  // steps are taken:
 246                  // 1. Let boundArgs be the value of F's [[BoundArgs]] internal
 247                  //   property.
 248                  // 2. Let boundThis be the value of F's [[BoundThis]] internal
 249                  //   property.
 250                  // 3. Let target be the value of F's [[TargetFunction]] internal
 251                  //   property.
 252                  // 4. Let args be a new list containing the same values as the
 253                  //   list boundArgs in the same order followed by the same
 254                  //   values as the list ExtraArgs in the same order.
 255                  // 5. Return the result of calling the [[Call]] internal method
 256                  //   of target providing boundThis as the this value and
 257                  //   providing args as the arguments.
 258  
 259                  // equiv: target.call(this, ...boundArgs, ...args)
 260                  return target.apply(
 261                      that,
 262                      args.concat(_Array_slice_.call(arguments))
 263                  );
 264  
 265              }
 266  
 267          };
 268  
 269          // 15. If the [[Class]] internal property of Target is "Function", then
 270          //     a. Let L be the length property of Target minus the length of A.
 271          //     b. Set the length own property of F to either 0 or L, whichever is
 272          //       larger.
 273          // 16. Else set the length own property of F to 0.
 274  
 275          var boundLength = Math.max(0, target.length - args.length);
 276  
 277          // 17. Set the attributes of the length own property of F to the values
 278          //   specified in 15.3.5.1.
 279          var boundArgs = [];
 280          for (var i = 0; i < boundLength; i++) {
 281              boundArgs.push("$" + i);
 282          }
 283  
 284          // XXX Build a dynamic function with desired amount of arguments is the only
 285          // way to set the length property of a function.
 286          // In environments where Content Security Policies enabled (Chrome extensions,
 287          // for ex.) all use of eval or Function costructor throws an exception.
 288          // However in all of these environments Function.prototype.bind exists
 289          // and so this code will never be executed.
 290          var bound = Function("binder", "return function (" + boundArgs.join(",") + "){return binder.apply(this,arguments)}")(binder);
 291  
 292          if (target.prototype) {
 293              Empty.prototype = target.prototype;
 294              bound.prototype = new Empty();
 295              // Clean up dangling references.
 296              Empty.prototype = null;
 297          }
 298  
 299          // TODO
 300          // 18. Set the [[Extensible]] internal property of F to true.
 301  
 302          // TODO
 303          // 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3).
 304          // 20. Call the [[DefineOwnProperty]] internal method of F with
 305          //   arguments "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]:
 306          //   thrower, [[Enumerable]]: false, [[Configurable]]: false}, and
 307          //   false.
 308          // 21. Call the [[DefineOwnProperty]] internal method of F with
 309          //   arguments "arguments", PropertyDescriptor {[[Get]]: thrower,
 310          //   [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false},
 311          //   and false.
 312  
 313          // TODO
 314          // NOTE Function objects created using Function.prototype.bind do not
 315          // have a prototype property or the [[Code]], [[FormalParameters]], and
 316          // [[Scope]] internal properties.
 317          // XXX can't delete prototype in pure-js.
 318  
 319          // 22. Return F.
 320          return bound;
 321      }
 322  });
 323  
 324  // _Please note: Shortcuts are defined after `Function.prototype.bind` as we
 325  // us it in defining shortcuts.
 326  var owns = call.bind(ObjectPrototype.hasOwnProperty);
 327  
 328  // If JS engine supports accessors creating shortcuts.
 329  var defineGetter;
 330  var defineSetter;
 331  var lookupGetter;
 332  var lookupSetter;
 333  var supportsAccessors;
 334  if ((supportsAccessors = owns(ObjectPrototype, "__defineGetter__"))) {
 335      defineGetter = call.bind(ObjectPrototype.__defineGetter__);
 336      defineSetter = call.bind(ObjectPrototype.__defineSetter__);
 337      lookupGetter = call.bind(ObjectPrototype.__lookupGetter__);
 338      lookupSetter = call.bind(ObjectPrototype.__lookupSetter__);
 339  }
 340  
 341  //
 342  // Array
 343  // =====
 344  //
 345  
 346  // ES5 15.4.4.12
 347  // http://es5.github.com/#x15.4.4.12
 348  var spliceNoopReturnsEmptyArray = (function () {
 349      var a = [1, 2];
 350      var result = a.splice();
 351      return a.length === 2 && isArray(result) && result.length === 0;
 352  }());
 353  defineProperties(ArrayPrototype, {
 354      // Safari 5.0 bug where .splice() returns undefined
 355      splice: function splice(start, deleteCount) {
 356          if (arguments.length === 0) {
 357              return [];
 358          } else {
 359              return array_splice.apply(this, arguments);
 360          }
 361      }
 362  }, spliceNoopReturnsEmptyArray);
 363  
 364  var spliceWorksWithEmptyObject = (function () {
 365      var obj = {};
 366      ArrayPrototype.splice.call(obj, 0, 0, 1);
 367      return obj.length === 1;
 368  }());
 369  defineProperties(ArrayPrototype, {
 370      splice: function splice(start, deleteCount) {
 371          if (arguments.length === 0) { return []; }
 372          var args = arguments;
 373          this.length = Math.max(toInteger(this.length), 0);
 374          if (arguments.length > 0 && typeof deleteCount !== 'number') {
 375              args = _Array_slice_.call(arguments);
 376              if (args.length < 2) {
 377                  args.push(this.length - start);
 378              } else {
 379                  args[1] = toInteger(deleteCount);
 380              }
 381          }
 382          return array_splice.apply(this, args);
 383      }
 384  }, !spliceWorksWithEmptyObject);
 385  
 386  // ES5 15.4.4.12
 387  // http://es5.github.com/#x15.4.4.13
 388  // Return len+argCount.
 389  // [bugfix, ielt8]
 390  // IE < 8 bug: [].unshift(0) === undefined but should be "1"
 391  var hasUnshiftReturnValueBug = [].unshift(0) !== 1;
 392  defineProperties(ArrayPrototype, {
 393      unshift: function () {
 394          array_unshift.apply(this, arguments);
 395          return this.length;
 396      }
 397  }, hasUnshiftReturnValueBug);
 398  
 399  // ES5 15.4.3.2
 400  // http://es5.github.com/#x15.4.3.2
 401  // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray
 402  defineProperties(Array, { isArray: isArray });
 403  
 404  // The IsCallable() check in the Array functions
 405  // has been replaced with a strict check on the
 406  // internal class of the object to trap cases where
 407  // the provided function was actually a regular
 408  // expression literal, which in V8 and
 409  // JavaScriptCore is a typeof "function".  Only in
 410  // V8 are regular expression literals permitted as
 411  // reduce parameters, so it is desirable in the
 412  // general case for the shim to match the more
 413  // strict and common behavior of rejecting regular
 414  // expressions.
 415  
 416  // ES5 15.4.4.18
 417  // http://es5.github.com/#x15.4.4.18
 418  // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/forEach
 419  
 420  // Check failure of by-index access of string characters (IE < 9)
 421  // and failure of `0 in boxedString` (Rhino)
 422  var boxedString = Object("a");
 423  var splitString = boxedString[0] !== "a" || !(0 in boxedString);
 424  
 425  var properlyBoxesContext = function properlyBoxed(method) {
 426      // Check node 0.6.21 bug where third parameter is not boxed
 427      var properlyBoxesNonStrict = true;
 428      var properlyBoxesStrict = true;
 429      if (method) {
 430          method.call('foo', function (_, __, context) {
 431              if (typeof context !== 'object') { properlyBoxesNonStrict = false; }
 432          });
 433  
 434          method.call([1], function () {
 435              'use strict';
 436              properlyBoxesStrict = typeof this === 'string';
 437          }, 'x');
 438      }
 439      return !!method && properlyBoxesNonStrict && properlyBoxesStrict;
 440  };
 441  
 442  defineProperties(ArrayPrototype, {
 443      forEach: function forEach(fun /*, thisp*/) {
 444          var object = toObject(this),
 445              self = splitString && isString(this) ? this.split('') : object,
 446              thisp = arguments[1],
 447              i = -1,
 448              length = self.length >>> 0;
 449  
 450          // If no callback function or if callback is not a callable function
 451          if (!isFunction(fun)) {
 452              throw new TypeError(); // TODO message
 453          }
 454  
 455          while (++i < length) {
 456              if (i in self) {
 457                  // Invoke the callback function with call, passing arguments:
 458                  // context, property value, property key, thisArg object
 459                  // context
 460                  fun.call(thisp, self[i], i, object);
 461              }
 462          }
 463      }
 464  }, !properlyBoxesContext(ArrayPrototype.forEach));
 465  
 466  // ES5 15.4.4.19
 467  // http://es5.github.com/#x15.4.4.19
 468  // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map
 469  defineProperties(ArrayPrototype, {
 470      map: function map(fun /*, thisp*/) {
 471          var object = toObject(this),
 472              self = splitString && isString(this) ? this.split('') : object,
 473              length = self.length >>> 0,
 474              result = Array(length),
 475              thisp = arguments[1];
 476  
 477          // If no callback function or if callback is not a callable function
 478          if (!isFunction(fun)) {
 479              throw new TypeError(fun + " is not a function");
 480          }
 481  
 482          for (var i = 0; i < length; i++) {
 483              if (i in self) {
 484                  result[i] = fun.call(thisp, self[i], i, object);
 485              }
 486          }
 487          return result;
 488      }
 489  }, !properlyBoxesContext(ArrayPrototype.map));
 490  
 491  // ES5 15.4.4.20
 492  // http://es5.github.com/#x15.4.4.20
 493  // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter
 494  defineProperties(ArrayPrototype, {
 495      filter: function filter(fun /*, thisp */) {
 496          var object = toObject(this),
 497              self = splitString && isString(this) ? this.split('') : object,
 498              length = self.length >>> 0,
 499              result = [],
 500              value,
 501              thisp = arguments[1];
 502  
 503          // If no callback function or if callback is not a callable function
 504          if (!isFunction(fun)) {
 505              throw new TypeError(fun + " is not a function");
 506          }
 507  
 508          for (var i = 0; i < length; i++) {
 509              if (i in self) {
 510                  value = self[i];
 511                  if (fun.call(thisp, value, i, object)) {
 512                      result.push(value);
 513                  }
 514              }
 515          }
 516          return result;
 517      }
 518  }, !properlyBoxesContext(ArrayPrototype.filter));
 519  
 520  // ES5 15.4.4.16
 521  // http://es5.github.com/#x15.4.4.16
 522  // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every
 523  defineProperties(ArrayPrototype, {
 524      every: function every(fun /*, thisp */) {
 525          var object = toObject(this),
 526              self = splitString && isString(this) ? this.split('') : object,
 527              length = self.length >>> 0,
 528              thisp = arguments[1];
 529  
 530          // If no callback function or if callback is not a callable function
 531          if (!isFunction(fun)) {
 532              throw new TypeError(fun + " is not a function");
 533          }
 534  
 535          for (var i = 0; i < length; i++) {
 536              if (i in self && !fun.call(thisp, self[i], i, object)) {
 537                  return false;
 538              }
 539          }
 540          return true;
 541      }
 542  }, !properlyBoxesContext(ArrayPrototype.every));
 543  
 544  // ES5 15.4.4.17
 545  // http://es5.github.com/#x15.4.4.17
 546  // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some
 547  defineProperties(ArrayPrototype, {
 548      some: function some(fun /*, thisp */) {
 549          var object = toObject(this),
 550              self = splitString && isString(this) ? this.split('') : object,
 551              length = self.length >>> 0,
 552              thisp = arguments[1];
 553  
 554          // If no callback function or if callback is not a callable function
 555          if (!isFunction(fun)) {
 556              throw new TypeError(fun + " is not a function");
 557          }
 558  
 559          for (var i = 0; i < length; i++) {
 560              if (i in self && fun.call(thisp, self[i], i, object)) {
 561                  return true;
 562              }
 563          }
 564          return false;
 565      }
 566  }, !properlyBoxesContext(ArrayPrototype.some));
 567  
 568  // ES5 15.4.4.21
 569  // http://es5.github.com/#x15.4.4.21
 570  // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce
 571  var reduceCoercesToObject = false;
 572  if (ArrayPrototype.reduce) {
 573      reduceCoercesToObject = typeof ArrayPrototype.reduce.call('es5', function (_, __, ___, list) { return list; }) === 'object';
 574  }
 575  defineProperties(ArrayPrototype, {
 576      reduce: function reduce(fun /*, initial*/) {
 577          var object = toObject(this),
 578              self = splitString && isString(this) ? this.split('') : object,
 579              length = self.length >>> 0;
 580  
 581          // If no callback function or if callback is not a callable function
 582          if (!isFunction(fun)) {
 583              throw new TypeError(fun + " is not a function");
 584          }
 585  
 586          // no value to return if no initial value and an empty array
 587          if (!length && arguments.length === 1) {
 588              throw new TypeError("reduce of empty array with no initial value");
 589          }
 590  
 591          var i = 0;
 592          var result;
 593          if (arguments.length >= 2) {
 594              result = arguments[1];
 595          } else {
 596              do {
 597                  if (i in self) {
 598                      result = self[i++];
 599                      break;
 600                  }
 601  
 602                  // if array contains no values, no initial value to return
 603                  if (++i >= length) {
 604                      throw new TypeError("reduce of empty array with no initial value");
 605                  }
 606              } while (true);
 607          }
 608  
 609          for (; i < length; i++) {
 610              if (i in self) {
 611                  result = fun.call(void 0, result, self[i], i, object);
 612              }
 613          }
 614  
 615          return result;
 616      }
 617  }, !reduceCoercesToObject);
 618  
 619  // ES5 15.4.4.22
 620  // http://es5.github.com/#x15.4.4.22
 621  // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight
 622  var reduceRightCoercesToObject = false;
 623  if (ArrayPrototype.reduceRight) {
 624      reduceRightCoercesToObject = typeof ArrayPrototype.reduceRight.call('es5', function (_, __, ___, list) { return list; }) === 'object';
 625  }
 626  defineProperties(ArrayPrototype, {
 627      reduceRight: function reduceRight(fun /*, initial*/) {
 628          var object = toObject(this),
 629              self = splitString && isString(this) ? this.split('') : object,
 630              length = self.length >>> 0;
 631  
 632          // If no callback function or if callback is not a callable function
 633          if (!isFunction(fun)) {
 634              throw new TypeError(fun + " is not a function");
 635          }
 636  
 637          // no value to return if no initial value, empty array
 638          if (!length && arguments.length === 1) {
 639              throw new TypeError("reduceRight of empty array with no initial value");
 640          }
 641  
 642          var result, i = length - 1;
 643          if (arguments.length >= 2) {
 644              result = arguments[1];
 645          } else {
 646              do {
 647                  if (i in self) {
 648                      result = self[i--];
 649                      break;
 650                  }
 651  
 652                  // if array contains no values, no initial value to return
 653                  if (--i < 0) {
 654                      throw new TypeError("reduceRight of empty array with no initial value");
 655                  }
 656              } while (true);
 657          }
 658  
 659          if (i < 0) {
 660              return result;
 661          }
 662  
 663          do {
 664              if (i in self) {
 665                  result = fun.call(void 0, result, self[i], i, object);
 666              }
 667          } while (i--);
 668  
 669          return result;
 670      }
 671  }, !reduceRightCoercesToObject);
 672  
 673  // ES5 15.4.4.14
 674  // http://es5.github.com/#x15.4.4.14
 675  // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
 676  var hasFirefox2IndexOfBug = Array.prototype.indexOf && [0, 1].indexOf(1, 2) !== -1;
 677  defineProperties(ArrayPrototype, {
 678      indexOf: function indexOf(sought /*, fromIndex */ ) {
 679          var self = splitString && isString(this) ? this.split('') : toObject(this),
 680              length = self.length >>> 0;
 681  
 682          if (!length) {
 683              return -1;
 684          }
 685  
 686          var i = 0;
 687          if (arguments.length > 1) {
 688              i = toInteger(arguments[1]);
 689          }
 690  
 691          // handle negative indices
 692          i = i >= 0 ? i : Math.max(0, length + i);
 693          for (; i < length; i++) {
 694              if (i in self && self[i] === sought) {
 695                  return i;
 696              }
 697          }
 698          return -1;
 699      }
 700  }, hasFirefox2IndexOfBug);
 701  
 702  // ES5 15.4.4.15
 703  // http://es5.github.com/#x15.4.4.15
 704  // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf
 705  var hasFirefox2LastIndexOfBug = Array.prototype.lastIndexOf && [0, 1].lastIndexOf(0, -3) !== -1;
 706  defineProperties(ArrayPrototype, {
 707      lastIndexOf: function lastIndexOf(sought /*, fromIndex */) {
 708          var self = splitString && isString(this) ? this.split('') : toObject(this),
 709              length = self.length >>> 0;
 710  
 711          if (!length) {
 712              return -1;
 713          }
 714          var i = length - 1;
 715          if (arguments.length > 1) {
 716              i = Math.min(i, toInteger(arguments[1]));
 717          }
 718          // handle negative indices
 719          i = i >= 0 ? i : length - Math.abs(i);
 720          for (; i >= 0; i--) {
 721              if (i in self && sought === self[i]) {
 722                  return i;
 723              }
 724          }
 725          return -1;
 726      }
 727  }, hasFirefox2LastIndexOfBug);
 728  
 729  //
 730  // Object
 731  // ======
 732  //
 733  
 734  // ES5 15.2.3.14
 735  // http://es5.github.com/#x15.2.3.14
 736  
 737  // http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation
 738  var hasDontEnumBug = !({'toString': null}).propertyIsEnumerable('toString'),
 739      hasProtoEnumBug = (function () {}).propertyIsEnumerable('prototype'),
 740      dontEnums = [
 741          "toString",
 742          "toLocaleString",
 743          "valueOf",
 744          "hasOwnProperty",
 745          "isPrototypeOf",
 746          "propertyIsEnumerable",
 747          "constructor"
 748      ],
 749      dontEnumsLength = dontEnums.length;
 750  
 751  defineProperties(Object, {
 752      keys: function keys(object) {
 753          var isFn = isFunction(object),
 754              isArgs = isArguments(object),
 755              isObject = object !== null && typeof object === 'object',
 756              isStr = isObject && isString(object);
 757  
 758          if (!isObject && !isFn && !isArgs) {
 759              throw new TypeError("Object.keys called on a non-object");
 760          }
 761  
 762          var theKeys = [];
 763          var skipProto = hasProtoEnumBug && isFn;
 764          if (isStr || isArgs) {
 765              for (var i = 0; i < object.length; ++i) {
 766                  theKeys.push(String(i));
 767              }
 768          } else {
 769              for (var name in object) {
 770                  if (!(skipProto && name === 'prototype') && owns(object, name)) {
 771                      theKeys.push(String(name));
 772                  }
 773              }
 774          }
 775  
 776          if (hasDontEnumBug) {
 777              var ctor = object.constructor,
 778                  skipConstructor = ctor && ctor.prototype === object;
 779              for (var j = 0; j < dontEnumsLength; j++) {
 780                  var dontEnum = dontEnums[j];
 781                  if (!(skipConstructor && dontEnum === 'constructor') && owns(object, dontEnum)) {
 782                      theKeys.push(dontEnum);
 783                  }
 784              }
 785          }
 786          return theKeys;
 787      }
 788  });
 789  
 790  var keysWorksWithArguments = Object.keys && (function () {
 791      // Safari 5.0 bug
 792      return Object.keys(arguments).length === 2;
 793  }(1, 2));
 794  var originalKeys = Object.keys;
 795  defineProperties(Object, {
 796      keys: function keys(object) {
 797          if (isArguments(object)) {
 798              return originalKeys(ArrayPrototype.slice.call(object));
 799          } else {
 800              return originalKeys(object);
 801          }
 802      }
 803  }, !keysWorksWithArguments);
 804  
 805  //
 806  // Date
 807  // ====
 808  //
 809  
 810  // ES5 15.9.5.43
 811  // http://es5.github.com/#x15.9.5.43
 812  // This function returns a String value represent the instance in time
 813  // represented by this Date object. The format of the String is the Date Time
 814  // string format defined in 15.9.1.15. All fields are present in the String.
 815  // The time zone is always UTC, denoted by the suffix Z. If the time value of
 816  // this object is not a finite Number a RangeError exception is thrown.
 817  var negativeDate = -62198755200000;
 818  var negativeYearString = "-000001";
 819  var hasNegativeDateBug = Date.prototype.toISOString && new Date(negativeDate).toISOString().indexOf(negativeYearString) === -1;
 820  
 821  defineProperties(Date.prototype, {
 822      toISOString: function toISOString() {
 823          var result, length, value, year, month;
 824          if (!isFinite(this)) {
 825              throw new RangeError("Date.prototype.toISOString called on non-finite value.");
 826          }
 827  
 828          year = this.getUTCFullYear();
 829  
 830          month = this.getUTCMonth();
 831          // see https://github.com/es-shims/es5-shim/issues/111
 832          year += Math.floor(month / 12);
 833          month = (month % 12 + 12) % 12;
 834  
 835          // the date time string format is specified in 15.9.1.15.
 836          result = [month + 1, this.getUTCDate(), this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds()];
 837          year = (
 838              (year < 0 ? "-" : (year > 9999 ? "+" : "")) +
 839              ("00000" + Math.abs(year)).slice(0 <= year && year <= 9999 ? -4 : -6)
 840          );
 841  
 842          length = result.length;
 843          while (length--) {
 844              value = result[length];
 845              // pad months, days, hours, minutes, and seconds to have two
 846              // digits.
 847              if (value < 10) {
 848                  result[length] = "0" + value;
 849              }
 850          }
 851          // pad milliseconds to have three digits.
 852          return (
 853              year + "-" + result.slice(0, 2).join("-") +
 854              "T" + result.slice(2).join(":") + "." +
 855              ("000" + this.getUTCMilliseconds()).slice(-3) + "Z"
 856          );
 857      }
 858  }, hasNegativeDateBug);
 859  
 860  
 861  // ES5 15.9.5.44
 862  // http://es5.github.com/#x15.9.5.44
 863  // This function provides a String representation of a Date object for use by
 864  // JSON.stringify (15.12.3).
 865  var dateToJSONIsSupported = false;
 866  try {
 867      dateToJSONIsSupported = (
 868          Date.prototype.toJSON &&
 869          new Date(NaN).toJSON() === null &&
 870          new Date(negativeDate).toJSON().indexOf(negativeYearString) !== -1 &&
 871          Date.prototype.toJSON.call({ // generic
 872              toISOString: function () {
 873                  return true;
 874              }
 875          })
 876      );
 877  } catch (e) {
 878  }
 879  if (!dateToJSONIsSupported) {
 880      Date.prototype.toJSON = function toJSON(key) {
 881          // When the toJSON method is called with argument key, the following
 882          // steps are taken:
 883  
 884          // 1.  Let O be the result of calling ToObject, giving it the this
 885          // value as its argument.
 886          // 2. Let tv be toPrimitive(O, hint Number).
 887          var o = Object(this),
 888              tv = toPrimitive(o),
 889              toISO;
 890          // 3. If tv is a Number and is not finite, return null.
 891          if (typeof tv === "number" && !isFinite(tv)) {
 892              return null;
 893          }
 894          // 4. Let toISO be the result of calling the [[Get]] internal method of
 895          // O with argument "toISOString".
 896          toISO = o.toISOString;
 897          // 5. If IsCallable(toISO) is false, throw a TypeError exception.
 898          if (typeof toISO !== "function") {
 899              throw new TypeError("toISOString property is not callable");
 900          }
 901          // 6. Return the result of calling the [[Call]] internal method of
 902          //  toISO with O as the this value and an empty argument list.
 903          return toISO.call(o);
 904  
 905          // NOTE 1 The argument is ignored.
 906  
 907          // NOTE 2 The toJSON function is intentionally generic; it does not
 908          // require that its this value be a Date object. Therefore, it can be
 909          // transferred to other kinds of objects for use as a method. However,
 910          // it does require that any such object have a toISOString method. An
 911          // object is free to use the argument key to filter its
 912          // stringification.
 913      };
 914  }
 915  
 916  // ES5 15.9.4.2
 917  // http://es5.github.com/#x15.9.4.2
 918  // based on work shared by Daniel Friesen (dantman)
 919  // http://gist.github.com/303249
 920  var supportsExtendedYears = Date.parse('+033658-09-27T01:46:40.000Z') === 1e15;
 921  var acceptsInvalidDates = !isNaN(Date.parse('2012-04-04T24:00:00.500Z')) || !isNaN(Date.parse('2012-11-31T23:59:59.000Z'));
 922  var doesNotParseY2KNewYear = isNaN(Date.parse("2000-01-01T00:00:00.000Z"));
 923  if (!Date.parse || doesNotParseY2KNewYear || acceptsInvalidDates || !supportsExtendedYears) {
 924      // XXX global assignment won't work in embeddings that use
 925      // an alternate object for the context.
 926      Date = (function (NativeDate) {
 927  
 928          // Date.length === 7
 929          function Date(Y, M, D, h, m, s, ms) {
 930              var length = arguments.length;
 931              if (this instanceof NativeDate) {
 932                  var date = length === 1 && String(Y) === Y ? // isString(Y)
 933                      // We explicitly pass it through parse:
 934                      new NativeDate(Date.parse(Y)) :
 935                      // We have to manually make calls depending on argument
 936                      // length here
 937                      length >= 7 ? new NativeDate(Y, M, D, h, m, s, ms) :
 938                      length >= 6 ? new NativeDate(Y, M, D, h, m, s) :
 939                      length >= 5 ? new NativeDate(Y, M, D, h, m) :
 940                      length >= 4 ? new NativeDate(Y, M, D, h) :
 941                      length >= 3 ? new NativeDate(Y, M, D) :
 942                      length >= 2 ? new NativeDate(Y, M) :
 943                      length >= 1 ? new NativeDate(Y) :
 944                                    new NativeDate();
 945                  // Prevent mixups with unfixed Date object
 946                  date.constructor = Date;
 947                  return date;
 948              }
 949              return NativeDate.apply(this, arguments);
 950          }
 951  
 952          // 15.9.1.15 Date Time String Format.
 953          var isoDateExpression = new RegExp("^" +
 954              "(\\d{4}|[\+\-]\\d{6})" + // four-digit year capture or sign +
 955                                        // 6-digit extended year
 956              "(?:-(\\d{2})" + // optional month capture
 957              "(?:-(\\d{2})" + // optional day capture
 958              "(?:" + // capture hours:minutes:seconds.milliseconds
 959                  "T(\\d{2})" + // hours capture
 960                  ":(\\d{2})" + // minutes capture
 961                  "(?:" + // optional :seconds.milliseconds
 962                      ":(\\d{2})" + // seconds capture
 963                      "(?:(\\.\\d{1,}))?" + // milliseconds capture
 964                  ")?" +
 965              "(" + // capture UTC offset component
 966                  "Z|" + // UTC capture
 967                  "(?:" + // offset specifier +/-hours:minutes
 968                      "([-+])" + // sign capture
 969                      "(\\d{2})" + // hours offset capture
 970                      ":(\\d{2})" + // minutes offset capture
 971                  ")" +
 972              ")?)?)?)?" +
 973          "$");
 974  
 975          var months = [
 976              0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
 977          ];
 978  
 979          function dayFromMonth(year, month) {
 980              var t = month > 1 ? 1 : 0;
 981              return (
 982                  months[month] +
 983                  Math.floor((year - 1969 + t) / 4) -
 984                  Math.floor((year - 1901 + t) / 100) +
 985                  Math.floor((year - 1601 + t) / 400) +
 986                  365 * (year - 1970)
 987              );
 988          }
 989  
 990          function toUTC(t) {
 991              return Number(new NativeDate(1970, 0, 1, 0, 0, 0, t));
 992          }
 993  
 994          // Copy any custom methods a 3rd party library may have added
 995          for (var key in NativeDate) {
 996              Date[key] = NativeDate[key];
 997          }
 998  
 999          // Copy "native" methods explicitly; they may be non-enumerable
1000          Date.now = NativeDate.now;
1001          Date.UTC = NativeDate.UTC;
1002          Date.prototype = NativeDate.prototype;
1003          Date.prototype.constructor = Date;
1004  
1005          // Upgrade Date.parse to handle simplified ISO 8601 strings
1006          Date.parse = function parse(string) {
1007              var match = isoDateExpression.exec(string);
1008              if (match) {
1009                  // parse months, days, hours, minutes, seconds, and milliseconds
1010                  // provide default values if necessary
1011                  // parse the UTC offset component
1012                  var year = Number(match[1]),
1013                      month = Number(match[2] || 1) - 1,
1014                      day = Number(match[3] || 1) - 1,
1015                      hour = Number(match[4] || 0),
1016                      minute = Number(match[5] || 0),
1017                      second = Number(match[6] || 0),
1018                      millisecond = Math.floor(Number(match[7] || 0) * 1000),
1019                      // When time zone is missed, local offset should be used
1020                      // (ES 5.1 bug)
1021                      // see https://bugs.ecmascript.org/show_bug.cgi?id=112
1022                      isLocalTime = Boolean(match[4] && !match[8]),
1023                      signOffset = match[9] === "-" ? 1 : -1,
1024                      hourOffset = Number(match[10] || 0),
1025                      minuteOffset = Number(match[11] || 0),
1026                      result;
1027                  if (
1028                      hour < (
1029                          minute > 0 || second > 0 || millisecond > 0 ?
1030                          24 : 25
1031                      ) &&
1032                      minute < 60 && second < 60 && millisecond < 1000 &&
1033                      month > -1 && month < 12 && hourOffset < 24 &&
1034                      minuteOffset < 60 && // detect invalid offsets
1035                      day > -1 &&
1036                      day < (
1037                          dayFromMonth(year, month + 1) -
1038                          dayFromMonth(year, month)
1039                      )
1040                  ) {
1041                      result = (
1042                          (dayFromMonth(year, month) + day) * 24 +
1043                          hour +
1044                          hourOffset * signOffset
1045                      ) * 60;
1046                      result = (
1047                          (result + minute + minuteOffset * signOffset) * 60 +
1048                          second
1049                      ) * 1000 + millisecond;
1050                      if (isLocalTime) {
1051                          result = toUTC(result);
1052                      }
1053                      if (-8.64e15 <= result && result <= 8.64e15) {
1054                          return result;
1055                      }
1056                  }
1057                  return NaN;
1058              }
1059              return NativeDate.parse.apply(this, arguments);
1060          };
1061  
1062          return Date;
1063      })(Date);
1064  }
1065  
1066  // ES5 15.9.4.4
1067  // http://es5.github.com/#x15.9.4.4
1068  if (!Date.now) {
1069      Date.now = function now() {
1070          return new Date().getTime();
1071      };
1072  }
1073  
1074  
1075  //
1076  // Number
1077  // ======
1078  //
1079  
1080  // ES5.1 15.7.4.5
1081  // http://es5.github.com/#x15.7.4.5
1082  var hasToFixedBugs = NumberPrototype.toFixed && (
1083    (0.00008).toFixed(3) !== '0.000'
1084    || (0.9).toFixed(0) !== '1'
1085    || (1.255).toFixed(2) !== '1.25'
1086    || (1000000000000000128).toFixed(0) !== "1000000000000000128"
1087  );
1088  
1089  var toFixedHelpers = {
1090    base: 1e7,
1091    size: 6,
1092    data: [0, 0, 0, 0, 0, 0],
1093    multiply: function multiply(n, c) {
1094        var i = -1;
1095        while (++i < toFixedHelpers.size) {
1096            c += n * toFixedHelpers.data[i];
1097            toFixedHelpers.data[i] = c % toFixedHelpers.base;
1098            c = Math.floor(c / toFixedHelpers.base);
1099        }
1100    },
1101    divide: function divide(n) {
1102        var i = toFixedHelpers.size, c = 0;
1103        while (--i >= 0) {
1104            c += toFixedHelpers.data[i];
1105            toFixedHelpers.data[i] = Math.floor(c / n);
1106            c = (c % n) * toFixedHelpers.base;
1107        }
1108    },
1109    numToString: function numToString() {
1110        var i = toFixedHelpers.size;
1111        var s = '';
1112        while (--i >= 0) {
1113            if (s !== '' || i === 0 || toFixedHelpers.data[i] !== 0) {
1114                var t = String(toFixedHelpers.data[i]);
1115                if (s === '') {
1116                    s = t;
1117                } else {
1118                    s += '0000000'.slice(0, 7 - t.length) + t;
1119                }
1120            }
1121        }
1122        return s;
1123    },
1124    pow: function pow(x, n, acc) {
1125        return (n === 0 ? acc : (n % 2 === 1 ? pow(x, n - 1, acc * x) : pow(x * x, n / 2, acc)));
1126    },
1127    log: function log(x) {
1128        var n = 0;
1129        while (x >= 4096) {
1130            n += 12;
1131            x /= 4096;
1132        }
1133        while (x >= 2) {
1134            n += 1;
1135            x /= 2;
1136        }
1137        return n;
1138    }
1139  };
1140  
1141  defineProperties(NumberPrototype, {
1142      toFixed: function toFixed(fractionDigits) {
1143          var f, x, s, m, e, z, j, k;
1144  
1145          // Test for NaN and round fractionDigits down
1146          f = Number(fractionDigits);
1147          f = f !== f ? 0 : Math.floor(f);
1148  
1149          if (f < 0 || f > 20) {
1150              throw new RangeError("Number.toFixed called with invalid number of decimals");
1151          }
1152  
1153          x = Number(this);
1154  
1155          // Test for NaN
1156          if (x !== x) {
1157              return "NaN";
1158          }
1159  
1160          // If it is too big or small, return the string value of the number
1161          if (x <= -1e21 || x >= 1e21) {
1162              return String(x);
1163          }
1164  
1165          s = "";
1166  
1167          if (x < 0) {
1168              s = "-";
1169              x = -x;
1170          }
1171  
1172          m = "0";
1173  
1174          if (x > 1e-21) {
1175              // 1e-21 < x < 1e21
1176              // -70 < log2(x) < 70
1177              e = toFixedHelpers.log(x * toFixedHelpers.pow(2, 69, 1)) - 69;
1178              z = (e < 0 ? x * toFixedHelpers.pow(2, -e, 1) : x / toFixedHelpers.pow(2, e, 1));
1179              z *= 0x10000000000000; // Math.pow(2, 52);
1180              e = 52 - e;
1181  
1182              // -18 < e < 122
1183              // x = z / 2 ^ e
1184              if (e > 0) {
1185                  toFixedHelpers.multiply(0, z);
1186                  j = f;
1187  
1188                  while (j >= 7) {
1189                      toFixedHelpers.multiply(1e7, 0);
1190                      j -= 7;
1191                  }
1192  
1193                  toFixedHelpers.multiply(toFixedHelpers.pow(10, j, 1), 0);
1194                  j = e - 1;
1195  
1196                  while (j >= 23) {
1197                      toFixedHelpers.divide(1 << 23);
1198                      j -= 23;
1199                  }
1200  
1201                  toFixedHelpers.divide(1 << j);
1202                  toFixedHelpers.multiply(1, 1);
1203                  toFixedHelpers.divide(2);
1204                  m = toFixedHelpers.numToString();
1205              } else {
1206                  toFixedHelpers.multiply(0, z);
1207                  toFixedHelpers.multiply(1 << (-e), 0);
1208                  m = toFixedHelpers.numToString() + '0.00000000000000000000'.slice(2, 2 + f);
1209              }
1210          }
1211  
1212          if (f > 0) {
1213              k = m.length;
1214  
1215              if (k <= f) {
1216                  m = s + '0.0000000000000000000'.slice(0, f - k + 2) + m;
1217              } else {
1218                  m = s + m.slice(0, k - f) + '.' + m.slice(k - f);
1219              }
1220          } else {
1221              m = s + m;
1222          }
1223  
1224          return m;
1225      }
1226  }, hasToFixedBugs);
1227  
1228  
1229  //
1230  // String
1231  // ======
1232  //
1233  
1234  // ES5 15.5.4.14
1235  // http://es5.github.com/#x15.5.4.14
1236  
1237  // [bugfix, IE lt 9, firefox 4, Konqueror, Opera, obscure browsers]
1238  // Many browsers do not split properly with regular expressions or they
1239  // do not perform the split correctly under obscure conditions.
1240  // See http://blog.stevenlevithan.com/archives/cross-browser-split
1241  // I've tested in many browsers and this seems to cover the deviant ones:
1242  //    'ab'.split(/(?:ab)*/) should be ["", ""], not [""]
1243  //    '.'.split(/(.?)(.?)/) should be ["", ".", "", ""], not ["", ""]
1244  //    'tesst'.split(/(s)*/) should be ["t", undefined, "e", "s", "t"], not
1245  //       [undefined, "t", undefined, "e", ...]
1246  //    ''.split(/.?/) should be [], not [""]
1247  //    '.'.split(/()()/) should be ["."], not ["", "", "."]
1248  
1249  var string_split = StringPrototype.split;
1250  if (
1251      'ab'.split(/(?:ab)*/).length !== 2 ||
1252      '.'.split(/(.?)(.?)/).length !== 4 ||
1253      'tesst'.split(/(s)*/)[1] === "t" ||
1254      'test'.split(/(?:)/, -1).length !== 4 ||
1255      ''.split(/.?/).length ||
1256      '.'.split(/()()/).length > 1
1257  ) {
1258      (function () {
1259          var compliantExecNpcg = /()??/.exec("")[1] === void 0; // NPCG: nonparticipating capturing group
1260  
1261          StringPrototype.split = function (separator, limit) {
1262              var string = this;
1263              if (separator === void 0 && limit === 0) {
1264                  return [];
1265              }
1266  
1267              // If `separator` is not a regex, use native split
1268              if (_toString.call(separator) !== "[object RegExp]") {
1269                  return string_split.call(this, separator, limit);
1270              }
1271  
1272              var output = [],
1273                  flags = (separator.ignoreCase ? "i" : "") +
1274                          (separator.multiline  ? "m" : "") +
1275                          (separator.extended   ? "x" : "") + // Proposed for ES6
1276                          (separator.sticky     ? "y" : ""), // Firefox 3+
1277                  lastLastIndex = 0,
1278                  // Make `global` and avoid `lastIndex` issues by working with a copy
1279                  separator2, match, lastIndex, lastLength;
1280              separator = new RegExp(separator.source, flags + "g");
1281              string += ""; // Type-convert
1282              if (!compliantExecNpcg) {
1283                  // Doesn't need flags gy, but they don't hurt
1284                  separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags);
1285              }
1286              /* Values for `limit`, per the spec:
1287               * If undefined: 4294967295 // Math.pow(2, 32) - 1
1288               * If 0, Infinity, or NaN: 0
1289               * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
1290               * If negative number: 4294967296 - Math.floor(Math.abs(limit))
1291               * If other: Type-convert, then use the above rules
1292               */
1293              limit = limit === void 0 ?
1294                  -1 >>> 0 : // Math.pow(2, 32) - 1
1295                  ToUint32(limit);
1296              while (match = separator.exec(string)) {
1297                  // `separator.lastIndex` is not reliable cross-browser
1298                  lastIndex = match.index + match[0].length;
1299                  if (lastIndex > lastLastIndex) {
1300                      output.push(string.slice(lastLastIndex, match.index));
1301                      // Fix browsers whose `exec` methods don't consistently return `undefined` for
1302                      // nonparticipating capturing groups
1303                      if (!compliantExecNpcg && match.length > 1) {
1304                          match[0].replace(separator2, function () {
1305                              for (var i = 1; i < arguments.length - 2; i++) {
1306                                  if (arguments[i] === void 0) {
1307                                      match[i] = void 0;
1308                                  }
1309                              }
1310                          });
1311                      }
1312                      if (match.length > 1 && match.index < string.length) {
1313                          ArrayPrototype.push.apply(output, match.slice(1));
1314                      }
1315                      lastLength = match[0].length;
1316                      lastLastIndex = lastIndex;
1317                      if (output.length >= limit) {
1318                          break;
1319                      }
1320                  }
1321                  if (separator.lastIndex === match.index) {
1322                      separator.lastIndex++; // Avoid an infinite loop
1323                  }
1324              }
1325              if (lastLastIndex === string.length) {
1326                  if (lastLength || !separator.test("")) {
1327                      output.push("");
1328                  }
1329              } else {
1330                  output.push(string.slice(lastLastIndex));
1331              }
1332              return output.length > limit ? output.slice(0, limit) : output;
1333          };
1334      }());
1335  
1336  // [bugfix, chrome]
1337  // If separator is undefined, then the result array contains just one String,
1338  // which is the this value (converted to a String). If limit is not undefined,
1339  // then the output array is truncated so that it contains no more than limit
1340  // elements.
1341  // "0".split(undefined, 0) -> []
1342  } else if ("0".split(void 0, 0).length) {
1343      StringPrototype.split = function split(separator, limit) {
1344          if (separator === void 0 && limit === 0) { return []; }
1345          return string_split.call(this, separator, limit);
1346      };
1347  }
1348  
1349  var str_replace = StringPrototype.replace;
1350  var replaceReportsGroupsCorrectly = (function () {
1351      var groups = [];
1352      'x'.replace(/x(.)?/g, function (match, group) {
1353          groups.push(group);
1354      });
1355      return groups.length === 1 && typeof groups[0] === 'undefined';
1356  }());
1357  
1358  if (!replaceReportsGroupsCorrectly) {
1359      StringPrototype.replace = function replace(searchValue, replaceValue) {
1360          var isFn = isFunction(replaceValue);
1361          var hasCapturingGroups = isRegex(searchValue) && (/\)[*?]/).test(searchValue.source);
1362          if (!isFn || !hasCapturingGroups) {
1363              return str_replace.call(this, searchValue, replaceValue);
1364          } else {
1365              var wrappedReplaceValue = function (match) {
1366                  var length = arguments.length;
1367                  var originalLastIndex = searchValue.lastIndex;
1368                  searchValue.lastIndex = 0;
1369                  var args = searchValue.exec(match);
1370                  searchValue.lastIndex = originalLastIndex;
1371                  args.push(arguments[length - 2], arguments[length - 1]);
1372                  return replaceValue.apply(this, args);
1373              };
1374              return str_replace.call(this, searchValue, wrappedReplaceValue);
1375          }
1376      };
1377  }
1378  
1379  // ECMA-262, 3rd B.2.3
1380  // Not an ECMAScript standard, although ECMAScript 3rd Edition has a
1381  // non-normative section suggesting uniform semantics and it should be
1382  // normalized across all browsers
1383  // [bugfix, IE lt 9] IE < 9 substr() with negative value not working in IE
1384  var string_substr = StringPrototype.substr;
1385  var hasNegativeSubstrBug = "".substr && "0b".substr(-1) !== "b";
1386  defineProperties(StringPrototype, {
1387      substr: function substr(start, length) {
1388          return string_substr.call(
1389              this,
1390              start < 0 ? ((start = this.length + start) < 0 ? 0 : start) : start,
1391              length
1392          );
1393      }
1394  }, hasNegativeSubstrBug);
1395  
1396  // ES5 15.5.4.20
1397  // whitespace from: http://es5.github.io/#x15.5.4.20
1398  var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" +
1399      "\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" +
1400      "\u2029\uFEFF";
1401  var zeroWidth = '\u200b';
1402  var wsRegexChars = "[" + ws + "]";
1403  var trimBeginRegexp = new RegExp("^" + wsRegexChars + wsRegexChars + "*");
1404  var trimEndRegexp = new RegExp(wsRegexChars + wsRegexChars + "*$");
1405  var hasTrimWhitespaceBug = StringPrototype.trim && (ws.trim() || !zeroWidth.trim());
1406  defineProperties(StringPrototype, {
1407      // http://blog.stevenlevithan.com/archives/faster-trim-javascript
1408      // http://perfectionkills.com/whitespace-deviations/
1409      trim: function trim() {
1410          if (this === void 0 || this === null) {
1411              throw new TypeError("can't convert " + this + " to object");
1412          }
1413          return String(this).replace(trimBeginRegexp, "").replace(trimEndRegexp, "");
1414      }
1415  }, hasTrimWhitespaceBug);
1416  
1417  // ES-5 15.1.2.2
1418  if (parseInt(ws + '08') !== 8 || parseInt(ws + '0x16') !== 22) {
1419      parseInt = (function (origParseInt) {
1420          var hexRegex = /^0[xX]/;
1421          return function parseIntES5(str, radix) {
1422              str = String(str).trim();
1423              if (!Number(radix)) {
1424                  radix = hexRegex.test(str) ? 16 : 10;
1425              }
1426              return origParseInt(str, radix);
1427          };
1428      }(parseInt));
1429  }
1430  
1431  }));


Generated: Fri Nov 28 14:03:12 2014 Cross-referenced by PHPXref 0.7.1