2 * https://github.com/es-shims/es5-shim
3 * @license es5-shim Copyright 2009-2015 by contributors, MIT License
4 * see https://github.com/es-shims/es5-shim/blob/master/LICENSE
7 // vim: ts=4 sts=4 sw=4 expandtab
9 // Add semicolon to prevent IIFE from being passed as argument to concatenated code.
12 // UMD (Universal Module Definition)
13 // see https://github.com/umdjs/umd/blob/master/returnExports.js
14 (function (root, factory) {
17 /* global define, exports, module */
18 if (typeof define === 'function' && define.amd) {
19 // AMD. Register as an anonymous module.
21 } else if (typeof exports === 'object') {
22 // Node. Does not work with strict CommonJS, but
23 // only CommonJS-like enviroments that support module.exports,
25 module.exports = factory();
27 // Browser globals (root is window)
28 root.returnExports = factory();
33 * Brings an environment as close to ECMAScript 5 compliance
34 * as is possible with the facilities of erstwhile engines.
36 * Annotated ES5: http://es5.github.com/ (specific links below)
37 * ES5 Spec: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
38 * Required reading: http://javascriptweblog.wordpress.com/2011/12/05/extending-javascript-natives/
41 // Shortcut to an often accessed properties, in order to avoid multiple
42 // dereference that costs universally. This also holds a reference to known-good
45 var ArrayPrototype = $Array.prototype;
47 var ObjectPrototype = $Object.prototype;
48 var FunctionPrototype = Function.prototype;
50 var StringPrototype = $String.prototype;
52 var NumberPrototype = $Number.prototype;
53 var array_slice = ArrayPrototype.slice;
54 var array_splice = ArrayPrototype.splice;
55 var array_push = ArrayPrototype.push;
56 var array_unshift = ArrayPrototype.unshift;
57 var array_concat = ArrayPrototype.concat;
58 var call = FunctionPrototype.call;
62 // Having a toString local variable name breaks in Opera so use to_string.
63 var to_string = ObjectPrototype.toString;
65 var hasToStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol';
66 var isCallable; /* inlined from https://npmjs.com/is-callable */ var fnToStr = Function.prototype.toString, tryFunctionObject = function tryFunctionObject(value) { try { fnToStr.call(value); return true; } catch (e) { return false; } }, fnClass = '[object Function]', genClass = '[object GeneratorFunction]'; isCallable = function isCallable(value) { if (typeof value !== 'function') { return false; } if (hasToStringTag) { return tryFunctionObject(value); } var strClass = to_string.call(value); return strClass === fnClass || strClass === genClass; };
67 var isRegex; /* inlined from https://npmjs.com/is-regex */ var regexExec = RegExp.prototype.exec, tryRegexExec = function tryRegexExec(value) { try { regexExec.call(value); return true; } catch (e) { return false; } }, regexClass = '[object RegExp]'; isRegex = function isRegex(value) { if (typeof value !== 'object') { return false; } return hasToStringTag ? tryRegexExec(value) : to_string.call(value) === regexClass; };
68 var isString; /* inlined from https://npmjs.com/is-string */ var strValue = String.prototype.valueOf, tryStringObject = function tryStringObject(value) { try { strValue.call(value); return true; } catch (e) { return false; } }, stringClass = '[object String]'; isString = function isString(value) { if (typeof value === 'string') { return true; } if (typeof value !== 'object') { return false; } return hasToStringTag ? tryStringObject(value) : to_string.call(value) === stringClass; };
70 /* inlined from http://npmjs.com/define-properties */
71 var defineProperties = (function (has) {
72 var supportsDescriptors = $Object.defineProperty && (function () {
75 $Object.defineProperty(obj, 'x', { enumerable: false, value: obj });
76 for (var _ in obj) { return false; }
78 } catch (e) { /* this is ES3 */
83 // Define configurable, writable and non-enumerable props
84 // if they don't exist.
86 if (supportsDescriptors) {
87 defineProperty = function (object, name, method, forceAssign) {
88 if (!forceAssign && (name in object)) { return; }
89 $Object.defineProperty(object, name, {
97 defineProperty = function (object, name, method, forceAssign) {
98 if (!forceAssign && (name in object)) { return; }
99 object[name] = method;
102 return function defineProperties(object, map, forceAssign) {
103 for (var name in map) {
104 if (has.call(map, name)) {
105 defineProperty(object, name, map[name], forceAssign);
109 }(ObjectPrototype.hasOwnProperty));
116 /* replaceable with https://npmjs.com/package/es-abstract /helpers/isPrimitive */
117 var isPrimitive = function isPrimitive(input) {
118 var type = typeof input;
119 return input === null || (type !== 'object' && type !== 'function');
122 var isActualNaN = $Number.isNaN || function (x) { return x !== x; };
126 // http://es5.github.com/#x9.4
127 // http://jsperf.com/to-integer
128 /* replaceable with https://npmjs.com/package/es-abstract ES5.ToInteger */
129 ToInteger: function ToInteger(num) {
131 if (isActualNaN(n)) {
133 } else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) {
134 n = (n > 0 || -1) * Math.floor(Math.abs(n));
139 /* replaceable with https://npmjs.com/package/es-abstract ES5.ToPrimitive */
140 ToPrimitive: function ToPrimitive(input) {
141 var val, valueOf, toStr;
142 if (isPrimitive(input)) {
145 valueOf = input.valueOf;
146 if (isCallable(valueOf)) {
147 val = valueOf.call(input);
148 if (isPrimitive(val)) {
152 toStr = input.toString;
153 if (isCallable(toStr)) {
154 val = toStr.call(input);
155 if (isPrimitive(val)) {
159 throw new TypeError();
163 // http://es5.github.com/#x9.9
164 /* replaceable with https://npmjs.com/package/es-abstract ES5.ToObject */
165 ToObject: function (o) {
166 /* jshint eqnull: true */
167 if (o == null) { // this matches both null and undefined
168 throw new TypeError("can't convert " + o + ' to object');
173 /* replaceable with https://npmjs.com/package/es-abstract ES5.ToUint32 */
174 ToUint32: function ToUint32(x) {
185 // http://es5.github.com/#x15.3.4.5
187 var Empty = function Empty() {};
189 defineProperties(FunctionPrototype, {
190 bind: function bind(that) { // .length is 1
191 // 1. Let Target be the this value.
193 // 2. If IsCallable(Target) is false, throw a TypeError exception.
194 if (!isCallable(target)) {
195 throw new TypeError('Function.prototype.bind called on incompatible ' + target);
197 // 3. Let A be a new (possibly empty) internal list of all of the
198 // argument values provided after thisArg (arg1, arg2 etc), in order.
199 // XXX slicedArgs will stand in for "A" if used
200 var args = array_slice.call(arguments, 1); // for normal call
201 // 4. Let F be a new native ECMAScript object.
202 // 11. Set the [[Prototype]] internal property of F to the standard
203 // built-in Function prototype object as specified in 15.3.3.1.
204 // 12. Set the [[Call]] internal property of F as described in
206 // 13. Set the [[Construct]] internal property of F as described in
208 // 14. Set the [[HasInstance]] internal property of F as described in
211 var binder = function () {
213 if (this instanceof bound) {
214 // 15.3.4.5.2 [[Construct]]
215 // When the [[Construct]] internal method of a function object,
216 // F that was created using the bind function is called with a
217 // list of arguments ExtraArgs, the following steps are taken:
218 // 1. Let target be the value of F's [[TargetFunction]]
219 // internal property.
220 // 2. If target has no [[Construct]] internal method, a
221 // TypeError exception is thrown.
222 // 3. Let boundArgs be the value of F's [[BoundArgs]] internal
224 // 4. Let args be a new list containing the same values as the
225 // list boundArgs in the same order followed by the same
226 // values as the list ExtraArgs in the same order.
227 // 5. Return the result of calling the [[Construct]] internal
228 // method of target providing args as the arguments.
230 var result = target.apply(
232 array_concat.call(args, array_slice.call(arguments))
234 if ($Object(result) === result) {
240 // 15.3.4.5.1 [[Call]]
241 // When the [[Call]] internal method of a function object, F,
242 // which was created using the bind function is called with a
243 // this value and a list of arguments ExtraArgs, the following
245 // 1. Let boundArgs be the value of F's [[BoundArgs]] internal
247 // 2. Let boundThis be the value of F's [[BoundThis]] internal
249 // 3. Let target be the value of F's [[TargetFunction]] internal
251 // 4. Let args be a new list containing the same values as the
252 // list boundArgs in the same order followed by the same
253 // values as the list ExtraArgs in the same order.
254 // 5. Return the result of calling the [[Call]] internal method
255 // of target providing boundThis as the this value and
256 // providing args as the arguments.
258 // equiv: target.call(this, ...boundArgs, ...args)
261 array_concat.call(args, array_slice.call(arguments))
268 // 15. If the [[Class]] internal property of Target is "Function", then
269 // a. Let L be the length property of Target minus the length of A.
270 // b. Set the length own property of F to either 0 or L, whichever is
272 // 16. Else set the length own property of F to 0.
274 var boundLength = max(0, target.length - args.length);
276 // 17. Set the attributes of the length own property of F to the values
277 // specified in 15.3.5.1.
279 for (var i = 0; i < boundLength; i++) {
280 array_push.call(boundArgs, '$' + i);
283 // XXX Build a dynamic function with desired amount of arguments is the only
284 // way to set the length property of a function.
285 // In environments where Content Security Policies enabled (Chrome extensions,
286 // for ex.) all use of eval or Function costructor throws an exception.
287 // However in all of these environments Function.prototype.bind exists
288 // and so this code will never be executed.
289 bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this, arguments); }')(binder);
291 if (target.prototype) {
292 Empty.prototype = target.prototype;
293 bound.prototype = new Empty();
294 // Clean up dangling references.
295 Empty.prototype = null;
299 // 18. Set the [[Extensible]] internal property of F to true.
302 // 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3).
303 // 20. Call the [[DefineOwnProperty]] internal method of F with
304 // arguments "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]:
305 // thrower, [[Enumerable]]: false, [[Configurable]]: false}, and
307 // 21. Call the [[DefineOwnProperty]] internal method of F with
308 // arguments "arguments", PropertyDescriptor {[[Get]]: thrower,
309 // [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false},
313 // NOTE Function objects created using Function.prototype.bind do not
314 // have a prototype property or the [[Code]], [[FormalParameters]], and
315 // [[Scope]] internal properties.
316 // XXX can't delete prototype in pure-js.
323 // _Please note: Shortcuts are defined after `Function.prototype.bind` as we
324 // us it in defining shortcuts.
325 var owns = call.bind(ObjectPrototype.hasOwnProperty);
326 var toStr = call.bind(ObjectPrototype.toString);
327 var strSlice = call.bind(StringPrototype.slice);
328 var strSplit = call.bind(StringPrototype.split);
335 var isArray = $Array.isArray || function isArray(obj) {
336 return toStr(obj) === '[object Array]';
340 // http://es5.github.com/#x15.4.4.13
341 // Return len+argCount.
343 // IE < 8 bug: [].unshift(0) === undefined but should be "1"
344 var hasUnshiftReturnValueBug = [].unshift(0) !== 1;
345 defineProperties(ArrayPrototype, {
346 unshift: function () {
347 array_unshift.apply(this, arguments);
350 }, hasUnshiftReturnValueBug);
353 // http://es5.github.com/#x15.4.3.2
354 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray
355 defineProperties($Array, { isArray: isArray });
357 // The IsCallable() check in the Array functions
358 // has been replaced with a strict check on the
359 // internal class of the object to trap cases where
360 // the provided function was actually a regular
361 // expression literal, which in V8 and
362 // JavaScriptCore is a typeof "function". Only in
363 // V8 are regular expression literals permitted as
364 // reduce parameters, so it is desirable in the
365 // general case for the shim to match the more
366 // strict and common behavior of rejecting regular
370 // http://es5.github.com/#x15.4.4.18
371 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/forEach
373 // Check failure of by-index access of string characters (IE < 9)
374 // and failure of `0 in boxedString` (Rhino)
375 var boxedString = $Object('a');
376 var splitString = boxedString[0] !== 'a' || !(0 in boxedString);
378 var properlyBoxesContext = function properlyBoxed(method) {
379 // Check node 0.6.21 bug where third parameter is not boxed
380 var properlyBoxesNonStrict = true;
381 var properlyBoxesStrict = true;
383 method.call('foo', function (_, __, context) {
384 if (typeof context !== 'object') { properlyBoxesNonStrict = false; }
387 method.call([1], function () {
390 properlyBoxesStrict = typeof this === 'string';
393 return !!method && properlyBoxesNonStrict && properlyBoxesStrict;
396 defineProperties(ArrayPrototype, {
397 forEach: function forEach(callbackfn /*, thisArg*/) {
398 var object = ES.ToObject(this);
399 var self = splitString && isString(this) ? strSplit(this, '') : object;
401 var length = ES.ToUint32(self.length);
403 if (arguments.length > 1) {
407 // If no callback function or if callback is not a callable function
408 if (!isCallable(callbackfn)) {
409 throw new TypeError('Array.prototype.forEach callback must be a function');
412 while (++i < length) {
414 // Invoke the callback function with call, passing arguments:
415 // context, property value, property key, thisArg object
416 if (typeof T === 'undefined') {
417 callbackfn(self[i], i, object);
419 callbackfn.call(T, self[i], i, object);
424 }, !properlyBoxesContext(ArrayPrototype.forEach));
427 // http://es5.github.com/#x15.4.4.19
428 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map
429 defineProperties(ArrayPrototype, {
430 map: function map(callbackfn/*, thisArg*/) {
431 var object = ES.ToObject(this);
432 var self = splitString && isString(this) ? strSplit(this, '') : object;
433 var length = ES.ToUint32(self.length);
434 var result = $Array(length);
436 if (arguments.length > 1) {
440 // If no callback function or if callback is not a callable function
441 if (!isCallable(callbackfn)) {
442 throw new TypeError('Array.prototype.map callback must be a function');
445 for (var i = 0; i < length; i++) {
447 if (typeof T === 'undefined') {
448 result[i] = callbackfn(self[i], i, object);
450 result[i] = callbackfn.call(T, self[i], i, object);
456 }, !properlyBoxesContext(ArrayPrototype.map));
459 // http://es5.github.com/#x15.4.4.20
460 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter
461 defineProperties(ArrayPrototype, {
462 filter: function filter(callbackfn /*, thisArg*/) {
463 var object = ES.ToObject(this);
464 var self = splitString && isString(this) ? strSplit(this, '') : object;
465 var length = ES.ToUint32(self.length);
469 if (arguments.length > 1) {
473 // If no callback function or if callback is not a callable function
474 if (!isCallable(callbackfn)) {
475 throw new TypeError('Array.prototype.filter callback must be a function');
478 for (var i = 0; i < length; i++) {
481 if (typeof T === 'undefined' ? callbackfn(value, i, object) : callbackfn.call(T, value, i, object)) {
482 array_push.call(result, value);
488 }, !properlyBoxesContext(ArrayPrototype.filter));
491 // http://es5.github.com/#x15.4.4.16
492 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every
493 defineProperties(ArrayPrototype, {
494 every: function every(callbackfn /*, thisArg*/) {
495 var object = ES.ToObject(this);
496 var self = splitString && isString(this) ? strSplit(this, '') : object;
497 var length = ES.ToUint32(self.length);
499 if (arguments.length > 1) {
503 // If no callback function or if callback is not a callable function
504 if (!isCallable(callbackfn)) {
505 throw new TypeError('Array.prototype.every callback must be a function');
508 for (var i = 0; i < length; i++) {
509 if (i in self && !(typeof T === 'undefined' ? callbackfn(self[i], i, object) : callbackfn.call(T, self[i], i, object))) {
515 }, !properlyBoxesContext(ArrayPrototype.every));
518 // http://es5.github.com/#x15.4.4.17
519 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some
520 defineProperties(ArrayPrototype, {
521 some: function some(callbackfn/*, thisArg */) {
522 var object = ES.ToObject(this);
523 var self = splitString && isString(this) ? strSplit(this, '') : object;
524 var length = ES.ToUint32(self.length);
526 if (arguments.length > 1) {
530 // If no callback function or if callback is not a callable function
531 if (!isCallable(callbackfn)) {
532 throw new TypeError('Array.prototype.some callback must be a function');
535 for (var i = 0; i < length; i++) {
536 if (i in self && (typeof T === 'undefined' ? callbackfn(self[i], i, object) : callbackfn.call(T, self[i], i, object))) {
542 }, !properlyBoxesContext(ArrayPrototype.some));
545 // http://es5.github.com/#x15.4.4.21
546 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce
547 var reduceCoercesToObject = false;
548 if (ArrayPrototype.reduce) {
549 reduceCoercesToObject = typeof ArrayPrototype.reduce.call('es5', function (_, __, ___, list) { return list; }) === 'object';
551 defineProperties(ArrayPrototype, {
552 reduce: function reduce(callbackfn /*, initialValue*/) {
553 var object = ES.ToObject(this);
554 var self = splitString && isString(this) ? strSplit(this, '') : object;
555 var length = ES.ToUint32(self.length);
557 // If no callback function or if callback is not a callable function
558 if (!isCallable(callbackfn)) {
559 throw new TypeError('Array.prototype.reduce callback must be a function');
562 // no value to return if no initial value and an empty array
563 if (length === 0 && arguments.length === 1) {
564 throw new TypeError('reduce of empty array with no initial value');
569 if (arguments.length >= 2) {
570 result = arguments[1];
578 // if array contains no values, no initial value to return
580 throw new TypeError('reduce of empty array with no initial value');
585 for (; i < length; i++) {
587 result = callbackfn(result, self[i], i, object);
593 }, !reduceCoercesToObject);
596 // http://es5.github.com/#x15.4.4.22
597 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight
598 var reduceRightCoercesToObject = false;
599 if (ArrayPrototype.reduceRight) {
600 reduceRightCoercesToObject = typeof ArrayPrototype.reduceRight.call('es5', function (_, __, ___, list) { return list; }) === 'object';
602 defineProperties(ArrayPrototype, {
603 reduceRight: function reduceRight(callbackfn/*, initial*/) {
604 var object = ES.ToObject(this);
605 var self = splitString && isString(this) ? strSplit(this, '') : object;
606 var length = ES.ToUint32(self.length);
608 // If no callback function or if callback is not a callable function
609 if (!isCallable(callbackfn)) {
610 throw new TypeError('Array.prototype.reduceRight callback must be a function');
613 // no value to return if no initial value, empty array
614 if (length === 0 && arguments.length === 1) {
615 throw new TypeError('reduceRight of empty array with no initial value');
620 if (arguments.length >= 2) {
621 result = arguments[1];
629 // if array contains no values, no initial value to return
631 throw new TypeError('reduceRight of empty array with no initial value');
642 result = callbackfn(result, self[i], i, object);
648 }, !reduceRightCoercesToObject);
651 // http://es5.github.com/#x15.4.4.14
652 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
653 var hasFirefox2IndexOfBug = ArrayPrototype.indexOf && [0, 1].indexOf(1, 2) !== -1;
654 defineProperties(ArrayPrototype, {
655 indexOf: function indexOf(searchElement /*, fromIndex */) {
656 var self = splitString && isString(this) ? strSplit(this, '') : ES.ToObject(this);
657 var length = ES.ToUint32(self.length);
664 if (arguments.length > 1) {
665 i = ES.ToInteger(arguments[1]);
668 // handle negative indices
669 i = i >= 0 ? i : max(0, length + i);
670 for (; i < length; i++) {
671 if (i in self && self[i] === searchElement) {
677 }, hasFirefox2IndexOfBug);
680 // http://es5.github.com/#x15.4.4.15
681 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf
682 var hasFirefox2LastIndexOfBug = ArrayPrototype.lastIndexOf && [0, 1].lastIndexOf(0, -3) !== -1;
683 defineProperties(ArrayPrototype, {
684 lastIndexOf: function lastIndexOf(searchElement /*, fromIndex */) {
685 var self = splitString && isString(this) ? strSplit(this, '') : ES.ToObject(this);
686 var length = ES.ToUint32(self.length);
692 if (arguments.length > 1) {
693 i = min(i, ES.ToInteger(arguments[1]));
695 // handle negative indices
696 i = i >= 0 ? i : length - Math.abs(i);
697 for (; i >= 0; i--) {
698 if (i in self && searchElement === self[i]) {
704 }, hasFirefox2LastIndexOfBug);
707 // http://es5.github.com/#x15.4.4.12
708 var spliceNoopReturnsEmptyArray = (function () {
710 var result = a.splice();
711 return a.length === 2 && isArray(result) && result.length === 0;
713 defineProperties(ArrayPrototype, {
714 // Safari 5.0 bug where .splice() returns undefined
715 splice: function splice(start, deleteCount) {
716 if (arguments.length === 0) {
719 return array_splice.apply(this, arguments);
722 }, !spliceNoopReturnsEmptyArray);
724 var spliceWorksWithEmptyObject = (function () {
726 ArrayPrototype.splice.call(obj, 0, 0, 1);
727 return obj.length === 1;
729 defineProperties(ArrayPrototype, {
730 splice: function splice(start, deleteCount) {
731 if (arguments.length === 0) { return []; }
732 var args = arguments;
733 this.length = max(ES.ToInteger(this.length), 0);
734 if (arguments.length > 0 && typeof deleteCount !== 'number') {
735 args = array_slice.call(arguments);
736 if (args.length < 2) {
737 array_push.call(args, this.length - start);
739 args[1] = ES.ToInteger(deleteCount);
742 return array_splice.apply(this, args);
744 }, !spliceWorksWithEmptyObject);
745 var spliceWorksWithLargeSparseArrays = (function () {
746 // Per https://github.com/es-shims/es5-shim/issues/295
747 // Safari 7/8 breaks with sparse arrays of size 1e5 or greater
748 var arr = new $Array(1e5);
749 // note: the index MUST be 8 or larger or the test will false pass
752 // note: this test must be defined *after* the indexOf shim
753 // per https://github.com/es-shims/es5-shim/issues/313
754 return arr.indexOf('x') === 7;
756 var spliceWorksWithSmallSparseArrays = (function () {
757 // Per https://github.com/es-shims/es5-shim/issues/295
758 // Opera 12.15 breaks on this, no idea why.
762 arr.splice(n + 1, 0, 'b');
763 return arr[n] === 'a';
765 defineProperties(ArrayPrototype, {
766 splice: function splice(start, deleteCount) {
767 var O = ES.ToObject(this);
769 var len = ES.ToUint32(O.length);
770 var relativeStart = ES.ToInteger(start);
771 var actualStart = relativeStart < 0 ? max((len + relativeStart), 0) : min(relativeStart, len);
772 var actualDeleteCount = min(max(ES.ToInteger(deleteCount), 0), len - actualStart);
776 while (k < actualDeleteCount) {
777 from = $String(actualStart + k);
784 var items = array_slice.call(arguments, 2);
785 var itemCount = items.length;
787 if (itemCount < actualDeleteCount) {
789 while (k < (len - actualDeleteCount)) {
790 from = $String(k + actualDeleteCount);
791 to = $String(k + itemCount);
800 while (k > (len - actualDeleteCount + itemCount)) {
804 } else if (itemCount > actualDeleteCount) {
805 k = len - actualDeleteCount;
806 while (k > actualStart) {
807 from = $String(k + actualDeleteCount - 1);
808 to = $String(k + itemCount - 1);
818 for (var i = 0; i < items.length; ++i) {
822 O.length = len - actualDeleteCount + itemCount;
826 }, !spliceWorksWithLargeSparseArrays || !spliceWorksWithSmallSparseArrays);
834 // http://es5.github.com/#x15.2.3.14
836 // http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation
837 var hasDontEnumBug = !({ 'toString': null }).propertyIsEnumerable('toString');
838 var hasProtoEnumBug = function () {}.propertyIsEnumerable('prototype');
839 var hasStringEnumBug = !owns('x', '0');
840 var equalsConstructorPrototype = function (o) {
841 var ctor = o.constructor;
842 return ctor && ctor.prototype === o;
844 var blacklistedKeys = {
852 $webkitIndexedDB: true,
853 $webkitStorageInfo: true
855 var hasAutomationEqualityBug = (function () {
857 if (typeof window === 'undefined') { return false; }
858 for (var k in window) {
860 if (!blacklistedKeys['$' + k] && owns(window, k) && window[k] !== null && typeof window[k] === 'object') {
861 equalsConstructorPrototype(window[k]);
869 var equalsConstructorPrototypeIfNotBuggy = function (object) {
870 if (typeof window === 'undefined' || !hasAutomationEqualityBug) { return equalsConstructorPrototype(object); }
872 return equalsConstructorPrototype(object);
883 'propertyIsEnumerable',
886 var dontEnumsLength = dontEnums.length;
888 // taken directly from https://github.com/ljharb/is-arguments/blob/master/index.js
889 // can be replaced with require('is-arguments') if we ever use a build process instead
890 var isStandardArguments = function isArguments(value) {
891 return toStr(value) === '[object Arguments]';
893 var isLegacyArguments = function isArguments(value) {
894 return value !== null &&
895 typeof value === 'object' &&
896 typeof value.length === 'number' &&
899 isCallable(value.callee);
901 var isArguments = isStandardArguments(arguments) ? isStandardArguments : isLegacyArguments;
903 defineProperties($Object, {
904 keys: function keys(object) {
905 var isFn = isCallable(object);
906 var isArgs = isArguments(object);
907 var isObject = object !== null && typeof object === 'object';
908 var isStr = isObject && isString(object);
910 if (!isObject && !isFn && !isArgs) {
911 throw new TypeError('Object.keys called on a non-object');
915 var skipProto = hasProtoEnumBug && isFn;
916 if ((isStr && hasStringEnumBug) || isArgs) {
917 for (var i = 0; i < object.length; ++i) {
918 array_push.call(theKeys, $String(i));
923 for (var name in object) {
924 if (!(skipProto && name === 'prototype') && owns(object, name)) {
925 array_push.call(theKeys, $String(name));
930 if (hasDontEnumBug) {
931 var skipConstructor = equalsConstructorPrototypeIfNotBuggy(object);
932 for (var j = 0; j < dontEnumsLength; j++) {
933 var dontEnum = dontEnums[j];
934 if (!(skipConstructor && dontEnum === 'constructor') && owns(object, dontEnum)) {
935 array_push.call(theKeys, dontEnum);
943 var keysWorksWithArguments = $Object.keys && (function () {
945 return $Object.keys(arguments).length === 2;
947 var keysHasArgumentsLengthBug = $Object.keys && (function () {
948 var argKeys = $Object.keys(arguments);
949 return arguments.length !== 1 || argKeys.length !== 1 || argKeys[0] !== 1;
951 var originalKeys = $Object.keys;
952 defineProperties($Object, {
953 keys: function keys(object) {
954 if (isArguments(object)) {
955 return originalKeys(array_slice.call(object));
957 return originalKeys(object);
960 }, !keysWorksWithArguments || keysHasArgumentsLengthBug);
968 // http://es5.github.com/#x15.9.5.43
969 // This function returns a String value represent the instance in time
970 // represented by this Date object. The format of the String is the Date Time
971 // string format defined in 15.9.1.15. All fields are present in the String.
972 // The time zone is always UTC, denoted by the suffix Z. If the time value of
973 // this object is not a finite Number a RangeError exception is thrown.
974 var negativeDate = -62198755200000;
975 var negativeYearString = '-000001';
976 var hasNegativeDateBug = Date.prototype.toISOString && new Date(negativeDate).toISOString().indexOf(negativeYearString) === -1;
977 var hasSafari51DateBug = Date.prototype.toISOString && new Date(-1).toISOString() !== '1969-12-31T23:59:59.999Z';
979 defineProperties(Date.prototype, {
980 toISOString: function toISOString() {
981 var result, length, value, year, month;
982 if (!isFinite(this)) {
983 throw new RangeError('Date.prototype.toISOString called on non-finite value.');
986 year = this.getUTCFullYear();
988 month = this.getUTCMonth();
989 // see https://github.com/es-shims/es5-shim/issues/111
990 year += Math.floor(month / 12);
991 month = (month % 12 + 12) % 12;
993 // the date time string format is specified in 15.9.1.15.
994 result = [month + 1, this.getUTCDate(), this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds()];
996 (year < 0 ? '-' : (year > 9999 ? '+' : '')) +
997 strSlice('00000' + Math.abs(year), (0 <= year && year <= 9999) ? -4 : -6)
1000 length = result.length;
1002 value = result[length];
1003 // pad months, days, hours, minutes, and seconds to have two
1006 result[length] = '0' + value;
1009 // pad milliseconds to have three digits.
1011 year + '-' + array_slice.call(result, 0, 2).join('-') +
1012 'T' + array_slice.call(result, 2).join(':') + '.' +
1013 strSlice('000' + this.getUTCMilliseconds(), -3) + 'Z'
1016 }, hasNegativeDateBug || hasSafari51DateBug);
1019 // http://es5.github.com/#x15.9.5.44
1020 // This function provides a String representation of a Date object for use by
1021 // JSON.stringify (15.12.3).
1022 var dateToJSONIsSupported = (function () {
1024 return Date.prototype.toJSON &&
1025 new Date(NaN).toJSON() === null &&
1026 new Date(negativeDate).toJSON().indexOf(negativeYearString) !== -1 &&
1027 Date.prototype.toJSON.call({ // generic
1028 toISOString: function () { return true; }
1034 if (!dateToJSONIsSupported) {
1035 Date.prototype.toJSON = function toJSON(key) {
1036 // When the toJSON method is called with argument key, the following
1039 // 1. Let O be the result of calling ToObject, giving it the this
1040 // value as its argument.
1041 // 2. Let tv be ES.ToPrimitive(O, hint Number).
1042 var O = $Object(this);
1043 var tv = ES.ToPrimitive(O);
1044 // 3. If tv is a Number and is not finite, return null.
1045 if (typeof tv === 'number' && !isFinite(tv)) {
1048 // 4. Let toISO be the result of calling the [[Get]] internal method of
1049 // O with argument "toISOString".
1050 var toISO = O.toISOString;
1051 // 5. If IsCallable(toISO) is false, throw a TypeError exception.
1052 if (!isCallable(toISO)) {
1053 throw new TypeError('toISOString property is not callable');
1055 // 6. Return the result of calling the [[Call]] internal method of
1056 // toISO with O as the this value and an empty argument list.
1057 return toISO.call(O);
1059 // NOTE 1 The argument is ignored.
1061 // NOTE 2 The toJSON function is intentionally generic; it does not
1062 // require that its this value be a Date object. Therefore, it can be
1063 // transferred to other kinds of objects for use as a method. However,
1064 // it does require that any such object have a toISOString method. An
1065 // object is free to use the argument key to filter its
1071 // http://es5.github.com/#x15.9.4.2
1072 // based on work shared by Daniel Friesen (dantman)
1073 // http://gist.github.com/303249
1074 var supportsExtendedYears = Date.parse('+033658-09-27T01:46:40.000Z') === 1e15;
1075 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'));
1076 var doesNotParseY2KNewYear = isNaN(Date.parse('2000-01-01T00:00:00.000Z'));
1077 if (doesNotParseY2KNewYear || acceptsInvalidDates || !supportsExtendedYears) {
1078 // XXX global assignment won't work in embeddings that use
1079 // an alternate object for the context.
1080 /* global Date: true */
1081 /* eslint-disable no-undef */
1082 var maxSafeUnsigned32Bit = Math.pow(2, 31) - 1;
1083 var secondsWithinMaxSafeUnsigned32Bit = Math.floor(maxSafeUnsigned32Bit / 1e3);
1084 var hasSafariSignedIntBug = isActualNaN(new Date(1970, 0, 1, 0, 0, 0, maxSafeUnsigned32Bit + 1).getTime());
1085 Date = (function (NativeDate) {
1086 /* eslint-enable no-undef */
1087 // Date.length === 7
1088 var DateShim = function Date(Y, M, D, h, m, s, ms) {
1089 var length = arguments.length;
1091 if (this instanceof NativeDate) {
1094 if (hasSafariSignedIntBug && length >= 7 && ms > maxSafeUnsigned32Bit) {
1095 // work around a Safari 8/9 bug where it treats the seconds as signed
1096 var msToShift = Math.floor(ms / maxSafeUnsigned32Bit) * maxSafeUnsigned32Bit;
1097 var sToShift = Math.floor(msToShift / 1e3);
1098 seconds += sToShift;
1099 millis -= sToShift * 1e3;
1101 date = length === 1 && $String(Y) === Y ? // isString(Y)
1102 // We explicitly pass it through parse:
1103 new NativeDate(DateShim.parse(Y)) :
1104 // We have to manually make calls depending on argument
1106 length >= 7 ? new NativeDate(Y, M, D, h, m, seconds, millis) :
1107 length >= 6 ? new NativeDate(Y, M, D, h, m, seconds) :
1108 length >= 5 ? new NativeDate(Y, M, D, h, m) :
1109 length >= 4 ? new NativeDate(Y, M, D, h) :
1110 length >= 3 ? new NativeDate(Y, M, D) :
1111 length >= 2 ? new NativeDate(Y, M) :
1112 length >= 1 ? new NativeDate(Y) :
1115 date = NativeDate.apply(this, arguments);
1117 if (!isPrimitive(date)) {
1118 // Prevent mixups with unfixed Date object
1119 defineProperties(date, { constructor: DateShim }, true);
1124 // 15.9.1.15 Date Time String Format.
1125 var isoDateExpression = new RegExp('^' +
1126 '(\\d{4}|[+-]\\d{6})' + // four-digit year capture or sign +
1127 // 6-digit extended year
1128 '(?:-(\\d{2})' + // optional month capture
1129 '(?:-(\\d{2})' + // optional day capture
1130 '(?:' + // capture hours:minutes:seconds.milliseconds
1131 'T(\\d{2})' + // hours capture
1132 ':(\\d{2})' + // minutes capture
1133 '(?:' + // optional :seconds.milliseconds
1134 ':(\\d{2})' + // seconds capture
1135 '(?:(\\.\\d{1,}))?' + // milliseconds capture
1137 '(' + // capture UTC offset component
1138 'Z|' + // UTC capture
1139 '(?:' + // offset specifier +/-hours:minutes
1140 '([-+])' + // sign capture
1141 '(\\d{2})' + // hours offset capture
1142 ':(\\d{2})' + // minutes offset capture
1147 var months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365];
1149 var dayFromMonth = function dayFromMonth(year, month) {
1150 var t = month > 1 ? 1 : 0;
1153 Math.floor((year - 1969 + t) / 4) -
1154 Math.floor((year - 1901 + t) / 100) +
1155 Math.floor((year - 1601 + t) / 400) +
1160 var toUTC = function toUTC(t) {
1163 if (hasSafariSignedIntBug && ms > maxSafeUnsigned32Bit) {
1164 // work around a Safari 8/9 bug where it treats the seconds as signed
1165 var msToShift = Math.floor(ms / maxSafeUnsigned32Bit) * maxSafeUnsigned32Bit;
1166 var sToShift = Math.floor(msToShift / 1e3);
1168 ms -= sToShift * 1e3;
1170 return $Number(new NativeDate(1970, 0, 1, 0, 0, s, ms));
1173 // Copy any custom methods a 3rd party library may have added
1174 for (var key in NativeDate) {
1175 if (owns(NativeDate, key)) {
1176 DateShim[key] = NativeDate[key];
1180 // Copy "native" methods explicitly; they may be non-enumerable
1181 defineProperties(DateShim, {
1182 now: NativeDate.now,
1185 DateShim.prototype = NativeDate.prototype;
1186 defineProperties(DateShim.prototype, {
1187 constructor: DateShim
1190 // Upgrade Date.parse to handle simplified ISO 8601 strings
1191 var parseShim = function parse(string) {
1192 var match = isoDateExpression.exec(string);
1194 // parse months, days, hours, minutes, seconds, and milliseconds
1195 // provide default values if necessary
1196 // parse the UTC offset component
1197 var year = $Number(match[1]),
1198 month = $Number(match[2] || 1) - 1,
1199 day = $Number(match[3] || 1) - 1,
1200 hour = $Number(match[4] || 0),
1201 minute = $Number(match[5] || 0),
1202 second = $Number(match[6] || 0),
1203 millisecond = Math.floor($Number(match[7] || 0) * 1000),
1204 // When time zone is missed, local offset should be used
1206 // see https://bugs.ecmascript.org/show_bug.cgi?id=112
1207 isLocalTime = Boolean(match[4] && !match[8]),
1208 signOffset = match[9] === '-' ? 1 : -1,
1209 hourOffset = $Number(match[10] || 0),
1210 minuteOffset = $Number(match[11] || 0),
1212 var hasMinutesOrSecondsOrMilliseconds = minute > 0 || second > 0 || millisecond > 0;
1214 hour < (hasMinutesOrSecondsOrMilliseconds ? 24 : 25) &&
1215 minute < 60 && second < 60 && millisecond < 1000 &&
1216 month > -1 && month < 12 && hourOffset < 24 &&
1217 minuteOffset < 60 && // detect invalid offsets
1219 day < (dayFromMonth(year, month + 1) - dayFromMonth(year, month))
1222 (dayFromMonth(year, month) + day) * 24 +
1224 hourOffset * signOffset
1227 (result + minute + minuteOffset * signOffset) * 60 +
1229 ) * 1000 + millisecond;
1231 result = toUTC(result);
1233 if (-8.64e15 <= result && result <= 8.64e15) {
1239 return NativeDate.parse.apply(this, arguments);
1241 defineProperties(DateShim, { parse: parseShim });
1245 /* global Date: false */
1249 // http://es5.github.com/#x15.9.4.4
1251 Date.now = function now() {
1252 return new Date().getTime();
1262 // http://es5.github.com/#x15.7.4.5
1263 var hasToFixedBugs = NumberPrototype.toFixed && (
1264 (0.00008).toFixed(3) !== '0.000' ||
1265 (0.9).toFixed(0) !== '1' ||
1266 (1.255).toFixed(2) !== '1.25' ||
1267 (1000000000000000128).toFixed(0) !== '1000000000000000128'
1270 var toFixedHelpers = {
1273 data: [0, 0, 0, 0, 0, 0],
1274 multiply: function multiply(n, c) {
1277 while (++i < toFixedHelpers.size) {
1278 c2 += n * toFixedHelpers.data[i];
1279 toFixedHelpers.data[i] = c2 % toFixedHelpers.base;
1280 c2 = Math.floor(c2 / toFixedHelpers.base);
1283 divide: function divide(n) {
1284 var i = toFixedHelpers.size, c = 0;
1286 c += toFixedHelpers.data[i];
1287 toFixedHelpers.data[i] = Math.floor(c / n);
1288 c = (c % n) * toFixedHelpers.base;
1291 numToString: function numToString() {
1292 var i = toFixedHelpers.size;
1295 if (s !== '' || i === 0 || toFixedHelpers.data[i] !== 0) {
1296 var t = $String(toFixedHelpers.data[i]);
1300 s += strSlice('0000000', 0, 7 - t.length) + t;
1306 pow: function pow(x, n, acc) {
1307 return (n === 0 ? acc : (n % 2 === 1 ? pow(x, n - 1, acc * x) : pow(x * x, n / 2, acc)));
1309 log: function log(x) {
1312 while (x2 >= 4096) {
1324 defineProperties(NumberPrototype, {
1325 toFixed: function toFixed(fractionDigits) {
1326 var f, x, s, m, e, z, j, k;
1328 // Test for NaN and round fractionDigits down
1329 f = $Number(fractionDigits);
1330 f = isActualNaN(f) ? 0 : Math.floor(f);
1332 if (f < 0 || f > 20) {
1333 throw new RangeError('Number.toFixed called with invalid number of decimals');
1338 if (isActualNaN(x)) {
1342 // If it is too big or small, return the string value of the number
1343 if (x <= -1e21 || x >= 1e21) {
1358 // -70 < log2(x) < 70
1359 e = toFixedHelpers.log(x * toFixedHelpers.pow(2, 69, 1)) - 69;
1360 z = (e < 0 ? x * toFixedHelpers.pow(2, -e, 1) : x / toFixedHelpers.pow(2, e, 1));
1361 z *= 0x10000000000000; // Math.pow(2, 52);
1367 toFixedHelpers.multiply(0, z);
1371 toFixedHelpers.multiply(1e7, 0);
1375 toFixedHelpers.multiply(toFixedHelpers.pow(10, j, 1), 0);
1379 toFixedHelpers.divide(1 << 23);
1383 toFixedHelpers.divide(1 << j);
1384 toFixedHelpers.multiply(1, 1);
1385 toFixedHelpers.divide(2);
1386 m = toFixedHelpers.numToString();
1388 toFixedHelpers.multiply(0, z);
1389 toFixedHelpers.multiply(1 << (-e), 0);
1390 m = toFixedHelpers.numToString() + strSlice('0.00000000000000000000', 2, 2 + f);
1398 m = s + strSlice('0.0000000000000000000', 0, f - k + 2) + m;
1400 m = s + strSlice(m, 0, k - f) + '.' + strSlice(m, k - f);
1416 // http://es5.github.com/#x15.5.4.14
1418 // [bugfix, IE lt 9, firefox 4, Konqueror, Opera, obscure browsers]
1419 // Many browsers do not split properly with regular expressions or they
1420 // do not perform the split correctly under obscure conditions.
1421 // See http://blog.stevenlevithan.com/archives/cross-browser-split
1422 // I've tested in many browsers and this seems to cover the deviant ones:
1423 // 'ab'.split(/(?:ab)*/) should be ["", ""], not [""]
1424 // '.'.split(/(.?)(.?)/) should be ["", ".", "", ""], not ["", ""]
1425 // 'tesst'.split(/(s)*/) should be ["t", undefined, "e", "s", "t"], not
1426 // [undefined, "t", undefined, "e", ...]
1427 // ''.split(/.?/) should be [], not [""]
1428 // '.'.split(/()()/) should be ["."], not ["", "", "."]
1431 'ab'.split(/(?:ab)*/).length !== 2 ||
1432 '.'.split(/(.?)(.?)/).length !== 4 ||
1433 'tesst'.split(/(s)*/)[1] === 't' ||
1434 'test'.split(/(?:)/, -1).length !== 4 ||
1435 ''.split(/.?/).length ||
1436 '.'.split(/()()/).length > 1
1439 var compliantExecNpcg = typeof (/()??/).exec('')[1] === 'undefined'; // NPCG: nonparticipating capturing group
1440 var maxSafe32BitInt = Math.pow(2, 32) - 1;
1442 StringPrototype.split = function (separator, limit) {
1444 if (typeof separator === 'undefined' && limit === 0) {
1448 // If `separator` is not a regex, use native split
1449 if (!isRegex(separator)) {
1450 return strSplit(this, separator, limit);
1454 var flags = (separator.ignoreCase ? 'i' : '') +
1455 (separator.multiline ? 'm' : '') +
1456 (separator.unicode ? 'u' : '') + // in ES6
1457 (separator.sticky ? 'y' : ''), // Firefox 3+ and ES6
1459 // Make `global` and avoid `lastIndex` issues by working with a copy
1460 separator2, match, lastIndex, lastLength;
1461 var separatorCopy = new RegExp(separator.source, flags + 'g');
1462 string += ''; // Type-convert
1463 if (!compliantExecNpcg) {
1464 // Doesn't need flags gy, but they don't hurt
1465 separator2 = new RegExp('^' + separatorCopy.source + '$(?!\\s)', flags);
1467 /* Values for `limit`, per the spec:
1468 * If undefined: 4294967295 // maxSafe32BitInt
1469 * If 0, Infinity, or NaN: 0
1470 * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
1471 * If negative number: 4294967296 - Math.floor(Math.abs(limit))
1472 * If other: Type-convert, then use the above rules
1474 var splitLimit = typeof limit === 'undefined' ? maxSafe32BitInt : ES.ToUint32(limit);
1475 match = separatorCopy.exec(string);
1477 // `separatorCopy.lastIndex` is not reliable cross-browser
1478 lastIndex = match.index + match[0].length;
1479 if (lastIndex > lastLastIndex) {
1480 array_push.call(output, strSlice(string, lastLastIndex, match.index));
1481 // Fix browsers whose `exec` methods don't consistently return `undefined` for
1482 // nonparticipating capturing groups
1483 if (!compliantExecNpcg && match.length > 1) {
1484 /* eslint-disable no-loop-func */
1485 match[0].replace(separator2, function () {
1486 for (var i = 1; i < arguments.length - 2; i++) {
1487 if (typeof arguments[i] === 'undefined') {
1492 /* eslint-enable no-loop-func */
1494 if (match.length > 1 && match.index < string.length) {
1495 array_push.apply(output, array_slice.call(match, 1));
1497 lastLength = match[0].length;
1498 lastLastIndex = lastIndex;
1499 if (output.length >= splitLimit) {
1503 if (separatorCopy.lastIndex === match.index) {
1504 separatorCopy.lastIndex++; // Avoid an infinite loop
1506 match = separatorCopy.exec(string);
1508 if (lastLastIndex === string.length) {
1509 if (lastLength || !separatorCopy.test('')) {
1510 array_push.call(output, '');
1513 array_push.call(output, strSlice(string, lastLastIndex));
1515 return output.length > splitLimit ? strSlice(output, 0, splitLimit) : output;
1520 // If separator is undefined, then the result array contains just one String,
1521 // which is the this value (converted to a String). If limit is not undefined,
1522 // then the output array is truncated so that it contains no more than limit
1524 // "0".split(undefined, 0) -> []
1525 } else if ('0'.split(void 0, 0).length) {
1526 StringPrototype.split = function split(separator, limit) {
1527 if (typeof separator === 'undefined' && limit === 0) { return []; }
1528 return strSplit(this, separator, limit);
1532 var str_replace = StringPrototype.replace;
1533 var replaceReportsGroupsCorrectly = (function () {
1535 'x'.replace(/x(.)?/g, function (match, group) {
1536 array_push.call(groups, group);
1538 return groups.length === 1 && typeof groups[0] === 'undefined';
1541 if (!replaceReportsGroupsCorrectly) {
1542 StringPrototype.replace = function replace(searchValue, replaceValue) {
1543 var isFn = isCallable(replaceValue);
1544 var hasCapturingGroups = isRegex(searchValue) && (/\)[*?]/).test(searchValue.source);
1545 if (!isFn || !hasCapturingGroups) {
1546 return str_replace.call(this, searchValue, replaceValue);
1548 var wrappedReplaceValue = function (match) {
1549 var length = arguments.length;
1550 var originalLastIndex = searchValue.lastIndex;
1551 searchValue.lastIndex = 0;
1552 var args = searchValue.exec(match) || [];
1553 searchValue.lastIndex = originalLastIndex;
1554 array_push.call(args, arguments[length - 2], arguments[length - 1]);
1555 return replaceValue.apply(this, args);
1557 return str_replace.call(this, searchValue, wrappedReplaceValue);
1562 // ECMA-262, 3rd B.2.3
1563 // Not an ECMAScript standard, although ECMAScript 3rd Edition has a
1564 // non-normative section suggesting uniform semantics and it should be
1565 // normalized across all browsers
1566 // [bugfix, IE lt 9] IE < 9 substr() with negative value not working in IE
1567 var string_substr = StringPrototype.substr;
1568 var hasNegativeSubstrBug = ''.substr && '0b'.substr(-1) !== 'b';
1569 defineProperties(StringPrototype, {
1570 substr: function substr(start, length) {
1571 var normalizedStart = start;
1573 normalizedStart = max(this.length + start, 0);
1575 return string_substr.call(this, normalizedStart, length);
1577 }, hasNegativeSubstrBug);
1580 // whitespace from: http://es5.github.io/#x15.5.4.20
1581 var ws = '\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003' +
1582 '\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028' +
1584 var zeroWidth = '\u200b';
1585 var wsRegexChars = '[' + ws + ']';
1586 var trimBeginRegexp = new RegExp('^' + wsRegexChars + wsRegexChars + '*');
1587 var trimEndRegexp = new RegExp(wsRegexChars + wsRegexChars + '*$');
1588 var hasTrimWhitespaceBug = StringPrototype.trim && (ws.trim() || !zeroWidth.trim());
1589 defineProperties(StringPrototype, {
1590 // http://blog.stevenlevithan.com/archives/faster-trim-javascript
1591 // http://perfectionkills.com/whitespace-deviations/
1592 trim: function trim() {
1593 if (typeof this === 'undefined' || this === null) {
1594 throw new TypeError("can't convert " + this + ' to object');
1596 return $String(this).replace(trimBeginRegexp, '').replace(trimEndRegexp, '');
1598 }, hasTrimWhitespaceBug);
1601 if (parseInt(ws + '08') !== 8 || parseInt(ws + '0x16') !== 22) {
1602 /* global parseInt: true */
1603 parseInt = (function (origParseInt) {
1604 var hexRegex = /^0[xX]/;
1605 return function parseInt(str, radix) {
1606 var string = $String(str).trim();
1607 var defaultedRadix = $Number(radix) || (hexRegex.test(string) ? 16 : 10);
1608 return origParseInt(string, defaultedRadix);