Advertisement
Romul81

ES5 Methods shim

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