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.
43 var ArrayPrototype
= Array
.prototype;
44 var ObjectPrototype
= Object
.prototype;
45 var FunctionPrototype
= Function
.prototype;
46 var StringPrototype
= String
.prototype;
47 var NumberPrototype
= Number
.prototype;
48 var array_slice
= ArrayPrototype
.slice
;
49 var array_splice
= ArrayPrototype
.splice
;
50 var array_push
= ArrayPrototype
.push
;
51 var array_unshift
= ArrayPrototype
.unshift
;
52 var array_concat
= ArrayPrototype
.concat
;
53 var call
= FunctionPrototype
.call
;
55 // Having a toString local variable name breaks in Opera so use to_string.
56 var to_string
= ObjectPrototype
.toString
;
58 var isArray
= Array
.isArray
|| function isArray(obj
) {
59 return to_string
.call(obj
) === '[object Array]';
62 var hasToStringTag
= typeof Symbol
=== 'function' && typeof Symbol
.toStringTag
=== 'symbol';
63 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
; };
64 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
; };
65 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
; };
67 var isArguments
= function isArguments(value
) {
68 var str
= to_string
.call(value
);
69 var isArgs
= str
=== '[object Arguments]';
71 isArgs
= !isArray(value
) &&
73 typeof value
=== 'object' &&
74 typeof value
.length
=== 'number' &&
76 isCallable(value
.callee
);
81 /* inlined from http://npmjs.com/define-properties */
82 var defineProperties
= (function (has
) {
83 var supportsDescriptors
= Object
.defineProperty
&& (function () {
86 Object
.defineProperty(obj
, 'x', { enumerable
: false, value
: obj
});
87 for (var _
in obj
) { return false; }
89 } catch (e
) { /* this is ES3 */
94 // Define configurable, writable and non-enumerable props
95 // if they don't exist.
97 if (supportsDescriptors
) {
98 defineProperty = function (object
, name
, method
, forceAssign
) {
99 if (!forceAssign
&& (name
in object
)) { return; }
100 Object
.defineProperty(object
, name
, {
108 defineProperty = function (object
, name
, method
, forceAssign
) {
109 if (!forceAssign
&& (name
in object
)) { return; }
110 object
[name
] = method
;
113 return function defineProperties(object
, map
, forceAssign
) {
114 for (var name
in map
) {
115 if (has
.call(map
, name
)) {
116 defineProperty(object
, name
, map
[name
], forceAssign
);
120 }(ObjectPrototype
.hasOwnProperty
));
127 /* replaceable with https://npmjs.com/package/es-abstract /helpers/isPrimitive */
128 var isPrimitive = function isPrimitive(input) {
129 var type = typeof input;
130 return input === null || (type !== 'object' && type !== 'function');
135 // http://es5.github.com/#x9.4
136 // http://jsperf.com/to-integer
137 /* replaceable with https://npmjs.com/package/es-abstract ES5.ToInteger */
138 ToInteger: function ToInteger(num) {
140 if (n !== n) { // isNaN
142 } else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) {
143 n = (n > 0 || -1) * Math.floor(Math.abs(n));
148 /* replaceable with https://npmjs.com/package/es-abstract ES5.ToPrimitive */
149 ToPrimitive: function ToPrimitive(input) {
150 var val, valueOf, toStr;
151 if (isPrimitive(input)) {
154 valueOf = input.valueOf;
155 if (isCallable(valueOf)) {
156 val = valueOf.call(input);
157 if (isPrimitive(val)) {
161 toStr = input.toString;
162 if (isCallable(toStr)) {
163 val = toStr.call(input);
164 if (isPrimitive(val)) {
168 throw new TypeError();
172 // http://es5.github.com/#x9.9
173 /* replaceable with https://npmjs.com/package/es-abstract ES5.ToObject */
174 ToObject: function (o) {
175 /*jshint eqnull: true */
176 if (o
== null) { // this matches both null and undefined
177 throw new TypeError("can't convert " + o
+ ' to object');
182 /* replaceable with https://npmjs.com/package/es-abstract ES5.ToUint32 */
183 ToUint32: function ToUint32(x) {
194 // http://es5.github.com/#x15.3.4.5
196 var Empty = function Empty() {};
198 defineProperties(FunctionPrototype, {
199 bind: function bind(that) { // .length is 1
200 // 1. Let Target be the this value.
202 // 2. If IsCallable(Target) is false, throw a TypeError exception.
203 if (!isCallable(target)) {
204 throw new TypeError('Function.prototype.bind called on incompatible ' + target);
206 // 3. Let A be a new (possibly empty) internal list of all of the
207 // argument values provided after thisArg (arg1, arg2 etc), in order.
208 // XXX slicedArgs will stand in for "A" if used
209 var args = array_slice.call(arguments, 1); // for normal call
210 // 4. Let F be a new native ECMAScript object.
211 // 11. Set the [[Prototype]] internal property of F to the standard
212 // built-in Function prototype object as specified in 15.3.3.1.
213 // 12. Set the [[Call]] internal property of F as described in
215 // 13. Set the [[Construct]] internal property of F as described in
217 // 14. Set the [[HasInstance]] internal property of F as described in
220 var binder = function () {
222 if (this instanceof bound) {
223 // 15.3.4.5.2 [[Construct]]
224 // When the [[Construct]] internal method of a function object,
225 // F that was created using the bind function is called with a
226 // list of arguments ExtraArgs, the following steps are taken:
227 // 1. Let target be the value of F's [[TargetFunction]]
228 // internal property.
229 // 2. If target has no [[Construct]] internal method, a
230 // TypeError exception is thrown.
231 // 3. Let boundArgs be the value of F's [[BoundArgs]] internal
233 // 4. Let args be a new list containing the same values as the
234 // list boundArgs in the same order followed by the same
235 // values as the list ExtraArgs in the same order.
236 // 5. Return the result of calling the [[Construct]] internal
237 // method of target providing args as the arguments.
239 var result = target.apply(
241 array_concat.call(args, array_slice.call(arguments))
243 if (Object(result) === result) {
249 // 15.3.4.5.1 [[Call]]
250 // When the [[Call]] internal method of a function object, F,
251 // which was created using the bind function is called with a
252 // this value and a list of arguments ExtraArgs, the following
254 // 1. Let boundArgs be the value of F's [[BoundArgs]] internal
256 // 2. Let boundThis be the value of F's [[BoundThis]] internal
258 // 3. Let target be the value of F's [[TargetFunction]] internal
260 // 4. Let args be a new list containing the same values as the
261 // list boundArgs in the same order followed by the same
262 // values as the list ExtraArgs in the same order.
263 // 5. Return the result of calling the [[Call]] internal method
264 // of target providing boundThis as the this value and
265 // providing args as the arguments.
267 // equiv: target.call(this, ...boundArgs, ...args)
270 array_concat.call(args, array_slice.call(arguments))
277 // 15. If the [[Class]] internal property of Target is "Function", then
278 // a. Let L be the length property of Target minus the length of A.
279 // b. Set the length own property of F to either 0 or L, whichever is
281 // 16. Else set the length own property of F to 0.
283 var boundLength = Math.max(0, target.length - args.length);
285 // 17. Set the attributes of the length own property of F to the values
286 // specified in 15.3.5.1.
288 for (var i = 0; i < boundLength; i++) {
289 boundArgs.push('$' + i);
292 // XXX Build a dynamic function with desired amount of arguments is the only
293 // way to set the length property of a function.
294 // In environments where Content Security Policies enabled (Chrome extensions,
295 // for ex.) all use of eval or Function costructor throws an exception.
296 // However in all of these environments Function.prototype.bind exists
297 // and so this code will never be executed.
298 bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this, arguments); }')(binder);
300 if (target.prototype) {
301 Empty.prototype = target.prototype;
302 bound.prototype = new Empty();
303 // Clean up dangling references.
304 Empty.prototype = null;
308 // 18. Set the [[Extensible]] internal property of F to true.
311 // 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3).
312 // 20. Call the [[DefineOwnProperty]] internal method of F with
313 // arguments "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]:
314 // thrower, [[Enumerable]]: false, [[Configurable]]: false}, and
316 // 21. Call the [[DefineOwnProperty]] internal method of F with
317 // arguments "arguments", PropertyDescriptor {[[Get]]: thrower,
318 // [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false},
322 // NOTE Function objects created using Function.prototype.bind do not
323 // have a prototype property or the [[Code]], [[FormalParameters]], and
324 // [[Scope]] internal properties.
325 // XXX can't delete prototype in pure-js.
332 // _Please note: Shortcuts are defined after `Function.prototype.bind` as we
333 // us it in defining shortcuts.
334 var owns = call.bind(ObjectPrototype.hasOwnProperty);
342 // http://es5.github.com/#x15.4.4.12
343 var spliceNoopReturnsEmptyArray = (function () {
345 var result = a.splice();
346 return a.length === 2 && isArray(result) && result.length === 0;
348 defineProperties(ArrayPrototype, {
349 // Safari 5.0 bug where .splice() returns undefined
350 splice: function splice(start, deleteCount) {
351 if (arguments.length === 0) {
354 return array_splice.apply(this, arguments);
357 }, !spliceNoopReturnsEmptyArray);
359 var spliceWorksWithEmptyObject = (function () {
361 ArrayPrototype.splice.call(obj, 0, 0, 1);
362 return obj.length === 1;
364 defineProperties(ArrayPrototype, {
365 splice: function splice(start, deleteCount) {
366 if (arguments.length === 0) { return []; }
367 var args = arguments;
368 this.length = Math.max(ES.ToInteger(this.length), 0);
369 if (arguments.length > 0 && typeof deleteCount !== 'number') {
370 args = array_slice.call(arguments);
371 if (args.length < 2) {
372 args.push(this.length - start);
374 args[1] = ES.ToInteger(deleteCount);
377 return array_splice.apply(this, args);
379 }, !spliceWorksWithEmptyObject);
382 // http://es5.github.com/#x15.4.4.13
383 // Return len+argCount.
385 // IE < 8 bug: [].unshift(0) === undefined but should be "1"
386 var hasUnshiftReturnValueBug = [].unshift(0) !== 1;
387 defineProperties(ArrayPrototype, {
388 unshift: function () {
389 array_unshift.apply(this, arguments);
392 }, hasUnshiftReturnValueBug);
395 // http://es5.github.com/#x15.4.3.2
396 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray
397 defineProperties(Array, { isArray: isArray });
399 // The IsCallable() check in the Array functions
400 // has been replaced with a strict check on the
401 // internal class of the object to trap cases where
402 // the provided function was actually a regular
403 // expression literal, which in V8 and
404 // JavaScriptCore is a typeof "function". Only in
405 // V8 are regular expression literals permitted as
406 // reduce parameters, so it is desirable in the
407 // general case for the shim to match the more
408 // strict and common behavior of rejecting regular
412 // http://es5.github.com/#x15.4.4.18
413 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/forEach
415 // Check failure of by-index access of string characters (IE < 9)
416 // and failure of `0 in boxedString` (Rhino)
417 var boxedString = Object('a');
418 var splitString = boxedString[0] !== 'a' || !(0 in boxedString);
420 var properlyBoxesContext = function properlyBoxed(method) {
421 // Check node 0.6.21 bug where third parameter is not boxed
422 var properlyBoxesNonStrict = true;
423 var properlyBoxesStrict = true;
425 method.call('foo', function (_, __, context) {
426 if (typeof context !== 'object') { properlyBoxesNonStrict = false; }
429 method.call([1], function () {
432 properlyBoxesStrict = typeof this === 'string';
435 return !!method && properlyBoxesNonStrict && properlyBoxesStrict;
438 defineProperties(ArrayPrototype, {
439 forEach: function forEach(callbackfn /*, thisArg*/) {
440 var object
= ES
.ToObject(this);
441 var self
= splitString
&& isString(this) ? this.split('') : object
;
443 var length
= self
.length
>>> 0;
445 if (arguments
.length
> 1) {
449 // If no callback function or if callback is not a callable function
450 if (!isCallable(callbackfn
)) {
451 throw new TypeError('Array.prototype.forEach callback must be a function');
454 while (++i
< length
) {
456 // Invoke the callback function with call, passing arguments:
457 // context, property value, property key, thisArg object
458 if (typeof T
!== 'undefined') {
459 callbackfn
.call(T
, self
[i
], i
, object
);
461 callbackfn(self
[i
], i
, object
);
466 }, !properlyBoxesContext(ArrayPrototype
.forEach
));
469 // http://es5.github.com/#x15.4.4.19
470 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map
471 defineProperties(ArrayPrototype
, {
472 map
: function map(callbackfn
/*, thisArg*/) {
473 var object
= ES
.ToObject(this);
474 var self
= splitString
&& isString(this) ? this.split('') : object
;
475 var length
= self
.length
>>> 0;
476 var result
= Array(length
);
478 if (arguments
.length
> 1) {
482 // If no callback function or if callback is not a callable function
483 if (!isCallable(callbackfn
)) {
484 throw new TypeError('Array.prototype.map callback must be a function');
487 for (var i
= 0; i
< length
; i
++) {
489 if (typeof T
!== 'undefined') {
490 result
[i
] = callbackfn
.call(T
, self
[i
], i
, object
);
492 result
[i
] = callbackfn(self
[i
], i
, object
);
498 }, !properlyBoxesContext(ArrayPrototype
.map
));
501 // http://es5.github.com/#x15.4.4.20
502 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter
503 defineProperties(ArrayPrototype
, {
504 filter
: function filter(callbackfn
/*, thisArg*/) {
505 var object
= ES
.ToObject(this);
506 var self
= splitString
&& isString(this) ? this.split('') : object
;
507 var length
= self
.length
>>> 0;
511 if (arguments
.length
> 1) {
515 // If no callback function or if callback is not a callable function
516 if (!isCallable(callbackfn
)) {
517 throw new TypeError('Array.prototype.filter callback must be a function');
520 for (var i
= 0; i
< length
; i
++) {
523 if (typeof T
=== 'undefined' ? callbackfn(value
, i
, object
) : callbackfn
.call(T
, value
, i
, object
)) {
530 }, !properlyBoxesContext(ArrayPrototype
.filter
));
533 // http://es5.github.com/#x15.4.4.16
534 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every
535 defineProperties(ArrayPrototype
, {
536 every
: function every(callbackfn
/*, thisArg*/) {
537 var object
= ES
.ToObject(this);
538 var self
= splitString
&& isString(this) ? this.split('') : object
;
539 var length
= self
.length
>>> 0;
541 if (arguments
.length
> 1) {
545 // If no callback function or if callback is not a callable function
546 if (!isCallable(callbackfn
)) {
547 throw new TypeError('Array.prototype.every callback must be a function');
550 for (var i
= 0; i
< length
; i
++) {
551 if (i
in self
&& !(typeof T
=== 'undefined' ? callbackfn(self
[i
], i
, object
) : callbackfn
.call(T
, self
[i
], i
, object
))) {
557 }, !properlyBoxesContext(ArrayPrototype
.every
));
560 // http://es5.github.com/#x15.4.4.17
561 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some
562 defineProperties(ArrayPrototype
, {
563 some
: function some(callbackfn
/*, thisArg */) {
564 var object
= ES
.ToObject(this);
565 var self
= splitString
&& isString(this) ? this.split('') : object
;
566 var length
= self
.length
>>> 0;
568 if (arguments
.length
> 1) {
572 // If no callback function or if callback is not a callable function
573 if (!isCallable(callbackfn
)) {
574 throw new TypeError('Array.prototype.some callback must be a function');
577 for (var i
= 0; i
< length
; i
++) {
578 if (i
in self
&& (typeof T
=== 'undefined' ? callbackfn(self
[i
], i
, object
) : callbackfn
.call(T
, self
[i
], i
, object
))) {
584 }, !properlyBoxesContext(ArrayPrototype
.some
));
587 // http://es5.github.com/#x15.4.4.21
588 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce
589 var reduceCoercesToObject
= false;
590 if (ArrayPrototype
.reduce
) {
591 reduceCoercesToObject
= typeof ArrayPrototype
.reduce
.call('es5', function (_
, __
, ___
, list
) { return list
; }) === 'object';
593 defineProperties(ArrayPrototype
, {
594 reduce
: function reduce(callbackfn
/*, initialValue*/) {
595 var object
= ES
.ToObject(this);
596 var self
= splitString
&& isString(this) ? this.split('') : object
;
597 var length
= self
.length
>>> 0;
599 // If no callback function or if callback is not a callable function
600 if (!isCallable(callbackfn
)) {
601 throw new TypeError('Array.prototype.reduce callback must be a function');
604 // no value to return if no initial value and an empty array
605 if (length
=== 0 && arguments
.length
=== 1) {
606 throw new TypeError('reduce of empty array with no initial value');
611 if (arguments
.length
>= 2) {
612 result
= arguments
[1];
620 // if array contains no values, no initial value to return
622 throw new TypeError('reduce of empty array with no initial value');
627 for (; i
< length
; i
++) {
629 result
= callbackfn(result
, self
[i
], i
, object
);
635 }, !reduceCoercesToObject
);
638 // http://es5.github.com/#x15.4.4.22
639 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight
640 var reduceRightCoercesToObject
= false;
641 if (ArrayPrototype
.reduceRight
) {
642 reduceRightCoercesToObject
= typeof ArrayPrototype
.reduceRight
.call('es5', function (_
, __
, ___
, list
) { return list
; }) === 'object';
644 defineProperties(ArrayPrototype
, {
645 reduceRight
: function reduceRight(callbackfn
/*, initial*/) {
646 var object
= ES
.ToObject(this);
647 var self
= splitString
&& isString(this) ? this.split('') : object
;
648 var length
= self
.length
>>> 0;
650 // If no callback function or if callback is not a callable function
651 if (!isCallable(callbackfn
)) {
652 throw new TypeError('Array.prototype.reduceRight callback must be a function');
655 // no value to return if no initial value, empty array
656 if (length
=== 0 && arguments
.length
=== 1) {
657 throw new TypeError('reduceRight of empty array with no initial value');
662 if (arguments
.length
>= 2) {
663 result
= arguments
[1];
671 // if array contains no values, no initial value to return
673 throw new TypeError('reduceRight of empty array with no initial value');
684 result
= callbackfn(result
, self
[i
], i
, object
);
690 }, !reduceRightCoercesToObject
);
693 // http://es5.github.com/#x15.4.4.14
694 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
695 var hasFirefox2IndexOfBug
= Array
.prototype.indexOf
&& [0, 1].indexOf(1, 2) !== -1;
696 defineProperties(ArrayPrototype
, {
697 indexOf
: function indexOf(searchElement
/*, fromIndex */) {
698 var self
= splitString
&& isString(this) ? this.split('') : ES
.ToObject(this);
699 var length
= self
.length
>>> 0;
706 if (arguments
.length
> 1) {
707 i
= ES
.ToInteger(arguments
[1]);
710 // handle negative indices
711 i
= i
>= 0 ? i
: Math
.max(0, length
+ i
);
712 for (; i
< length
; i
++) {
713 if (i
in self
&& self
[i
] === searchElement
) {
719 }, hasFirefox2IndexOfBug
);
722 // http://es5.github.com/#x15.4.4.15
723 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf
724 var hasFirefox2LastIndexOfBug
= Array
.prototype.lastIndexOf
&& [0, 1].lastIndexOf(0, -3) !== -1;
725 defineProperties(ArrayPrototype
, {
726 lastIndexOf
: function lastIndexOf(searchElement
/*, fromIndex */) {
727 var self
= splitString
&& isString(this) ? this.split('') : ES
.ToObject(this);
728 var length
= self
.length
>>> 0;
734 if (arguments
.length
> 1) {
735 i
= Math
.min(i
, ES
.ToInteger(arguments
[1]));
737 // handle negative indices
738 i
= i
>= 0 ? i
: length
- Math
.abs(i
);
739 for (; i
>= 0; i
--) {
740 if (i
in self
&& searchElement
=== self
[i
]) {
746 }, hasFirefox2LastIndexOfBug
);
754 // http://es5.github.com/#x15.2.3.14
756 // http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation
757 var hasDontEnumBug
= !({ 'toString': null }).propertyIsEnumerable('toString'),
758 hasProtoEnumBug = function () {}.propertyIsEnumerable('prototype'),
759 hasStringEnumBug
= !owns('x', '0'),
766 'propertyIsEnumerable',
769 dontEnumsLength
= dontEnums
.length
;
771 defineProperties(Object
, {
772 keys
: function keys(object
) {
773 var isFn
= isCallable(object
),
774 isArgs
= isArguments(object
),
775 isObject
= object
!== null && typeof object
=== 'object',
776 isStr
= isObject
&& isString(object
);
778 if (!isObject
&& !isFn
&& !isArgs
) {
779 throw new TypeError('Object.keys called on a non-object');
783 var skipProto
= hasProtoEnumBug
&& isFn
;
784 if ((isStr
&& hasStringEnumBug
) || isArgs
) {
785 for (var i
= 0; i
< object
.length
; ++i
) {
786 theKeys
.push(String(i
));
791 for (var name
in object
) {
792 if (!(skipProto
&& name
=== 'prototype') && owns(object
, name
)) {
793 theKeys
.push(String(name
));
798 if (hasDontEnumBug
) {
799 var ctor
= object
.constructor,
800 skipConstructor
= ctor
&& ctor
.prototype === object
;
801 for (var j
= 0; j
< dontEnumsLength
; j
++) {
802 var dontEnum
= dontEnums
[j
];
803 if (!(skipConstructor
&& dontEnum
=== 'constructor') && owns(object
, dontEnum
)) {
804 theKeys
.push(dontEnum
);
812 var keysWorksWithArguments
= Object
.keys
&& (function () {
814 return Object
.keys(arguments
).length
=== 2;
816 var originalKeys
= Object
.keys
;
817 defineProperties(Object
, {
818 keys
: function keys(object
) {
819 if (isArguments(object
)) {
820 return originalKeys(ArrayPrototype
.slice
.call(object
));
822 return originalKeys(object
);
825 }, !keysWorksWithArguments
);
833 // http://es5.github.com/#x15.9.5.43
834 // This function returns a String value represent the instance in time
835 // represented by this Date object. The format of the String is the Date Time
836 // string format defined in 15.9.1.15. All fields are present in the String.
837 // The time zone is always UTC, denoted by the suffix Z. If the time value of
838 // this object is not a finite Number a RangeError exception is thrown.
839 var negativeDate
= -62198755200000;
840 var negativeYearString
= '-000001';
841 var hasNegativeDateBug
= Date
.prototype.toISOString
&& new Date(negativeDate
).toISOString().indexOf(negativeYearString
) === -1;
843 defineProperties(Date
.prototype, {
844 toISOString
: function toISOString() {
845 var result
, length
, value
, year
, month
;
846 if (!isFinite(this)) {
847 throw new RangeError('Date.prototype.toISOString called on non-finite value.');
850 year
= this.getUTCFullYear();
852 month
= this.getUTCMonth();
853 // see https://github.com/es-shims/es5-shim/issues/111
854 year
+= Math
.floor(month
/ 12);
855 month
= (month
% 12 + 12) % 12;
857 // the date time string format is specified in 15.9.1.15.
858 result
= [month
+ 1, this.getUTCDate(), this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds()];
860 (year
< 0 ? '-' : (year
> 9999 ? '+' : '')) +
861 ('00000' + Math
.abs(year
)).slice((0 <= year
&& year
<= 9999) ? -4 : -6)
864 length
= result
.length
;
866 value
= result
[length
];
867 // pad months, days, hours, minutes, and seconds to have two
870 result
[length
] = '0' + value
;
873 // pad milliseconds to have three digits.
875 year
+ '-' + result
.slice(0, 2).join('-') +
876 'T' + result
.slice(2).join(':') + '.' +
877 ('000' + this.getUTCMilliseconds()).slice(-3) + 'Z'
880 }, hasNegativeDateBug
);
883 // http://es5.github.com/#x15.9.5.44
884 // This function provides a String representation of a Date object for use by
885 // JSON.stringify (15.12.3).
886 var dateToJSONIsSupported
= (function () {
888 return Date
.prototype.toJSON
&&
889 new Date(NaN
).toJSON() === null &&
890 new Date(negativeDate
).toJSON().indexOf(negativeYearString
) !== -1 &&
891 Date
.prototype.toJSON
.call({ // generic
892 toISOString: function () { return true; }
898 if (!dateToJSONIsSupported
) {
899 Date
.prototype.toJSON
= function toJSON(key
) {
900 // When the toJSON method is called with argument key, the following
903 // 1. Let O be the result of calling ToObject, giving it the this
904 // value as its argument.
905 // 2. Let tv be ES.ToPrimitive(O, hint Number).
906 var O
= Object(this);
907 var tv
= ES
.ToPrimitive(O
);
908 // 3. If tv is a Number and is not finite, return null.
909 if (typeof tv
=== 'number' && !isFinite(tv
)) {
912 // 4. Let toISO be the result of calling the [[Get]] internal method of
913 // O with argument "toISOString".
914 var toISO
= O
.toISOString
;
915 // 5. If IsCallable(toISO) is false, throw a TypeError exception.
916 if (!isCallable(toISO
)) {
917 throw new TypeError('toISOString property is not callable');
919 // 6. Return the result of calling the [[Call]] internal method of
920 // toISO with O as the this value and an empty argument list.
921 return toISO
.call(O
);
923 // NOTE 1 The argument is ignored.
925 // NOTE 2 The toJSON function is intentionally generic; it does not
926 // require that its this value be a Date object. Therefore, it can be
927 // transferred to other kinds of objects for use as a method. However,
928 // it does require that any such object have a toISOString method. An
929 // object is free to use the argument key to filter its
935 // http://es5.github.com/#x15.9.4.2
936 // based on work shared by Daniel Friesen (dantman)
937 // http://gist.github.com/303249
938 var supportsExtendedYears
= Date
.parse('+033658-09-27T01:46:40.000Z') === 1e15
;
939 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'));
940 var doesNotParseY2KNewYear
= isNaN(Date
.parse('2000-01-01T00:00:00.000Z'));
941 if (!Date
.parse
|| doesNotParseY2KNewYear
|| acceptsInvalidDates
|| !supportsExtendedYears
) {
942 // XXX global assignment won't work in embeddings that use
943 // an alternate object for the context.
944 /*global Date: true */
945 /*eslint-disable no-undef*/
946 Date
= (function (NativeDate
) {
947 /*eslint-enable no-undef*/
949 var DateShim
= function Date(Y
, M
, D
, h
, m
, s
, ms
) {
950 var length
= arguments
.length
;
952 if (this instanceof NativeDate
) {
953 date
= length
=== 1 && String(Y
) === Y
? // isString(Y)
954 // We explicitly pass it through parse:
955 new NativeDate(DateShim
.parse(Y
)) :
956 // We have to manually make calls depending on argument
958 length
>= 7 ? new NativeDate(Y
, M
, D
, h
, m
, s
, ms
) :
959 length
>= 6 ? new NativeDate(Y
, M
, D
, h
, m
, s
) :
960 length
>= 5 ? new NativeDate(Y
, M
, D
, h
, m
) :
961 length
>= 4 ? new NativeDate(Y
, M
, D
, h
) :
962 length
>= 3 ? new NativeDate(Y
, M
, D
) :
963 length
>= 2 ? new NativeDate(Y
, M
) :
964 length
>= 1 ? new NativeDate(Y
) :
967 date
= NativeDate
.apply(this, arguments
);
969 // Prevent mixups with unfixed Date object
970 defineProperties(date
, { constructor: DateShim
}, true);
974 // 15.9.1.15 Date Time String Format.
975 var isoDateExpression
= new RegExp('^' +
976 '(\\d{4}|[+-]\\d{6})' + // four-digit year capture or sign +
977 // 6-digit extended year
978 '(?:-(\\d{2})' + // optional month capture
979 '(?:-(\\d{2})' + // optional day capture
980 '(?:' + // capture hours:minutes:seconds.milliseconds
981 'T(\\d{2})' + // hours capture
982 ':(\\d{2})' + // minutes capture
983 '(?:' + // optional :seconds.milliseconds
984 ':(\\d{2})' + // seconds capture
985 '(?:(\\.\\d{1,}))?' + // milliseconds capture
987 '(' + // capture UTC offset component
988 'Z|' + // UTC capture
989 '(?:' + // offset specifier +/-hours:minutes
990 '([-+])' + // sign capture
991 '(\\d{2})' + // hours offset capture
992 ':(\\d{2})' + // minutes offset capture
997 var months
= [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365];
999 var dayFromMonth
= function dayFromMonth(year
, month
) {
1000 var t
= month
> 1 ? 1 : 0;
1003 Math
.floor((year
- 1969 + t
) / 4) -
1004 Math
.floor((year
- 1901 + t
) / 100) +
1005 Math
.floor((year
- 1601 + t
) / 400) +
1010 var toUTC
= function toUTC(t
) {
1011 return Number(new NativeDate(1970, 0, 1, 0, 0, 0, t
));
1014 // Copy any custom methods a 3rd party library may have added
1015 for (var key
in NativeDate
) {
1016 if (owns(NativeDate
, key
)) {
1017 DateShim
[key
] = NativeDate
[key
];
1021 // Copy "native" methods explicitly; they may be non-enumerable
1022 defineProperties(DateShim
, {
1023 now
: NativeDate
.now
,
1026 DateShim
.prototype = NativeDate
.prototype;
1027 defineProperties(DateShim
.prototype, {
1028 constructor: DateShim
1031 // Upgrade Date.parse to handle simplified ISO 8601 strings
1032 DateShim
.parse
= function parse(string
) {
1033 var match
= isoDateExpression
.exec(string
);
1035 // parse months, days, hours, minutes, seconds, and milliseconds
1036 // provide default values if necessary
1037 // parse the UTC offset component
1038 var year
= Number(match
[1]),
1039 month
= Number(match
[2] || 1) - 1,
1040 day
= Number(match
[3] || 1) - 1,
1041 hour
= Number(match
[4] || 0),
1042 minute
= Number(match
[5] || 0),
1043 second
= Number(match
[6] || 0),
1044 millisecond
= Math
.floor(Number(match
[7] || 0) * 1000),
1045 // When time zone is missed, local offset should be used
1047 // see https://bugs.ecmascript.org/show_bug.cgi?id=112
1048 isLocalTime
= Boolean(match
[4] && !match
[8]),
1049 signOffset
= match
[9] === '-' ? 1 : -1,
1050 hourOffset
= Number(match
[10] || 0),
1051 minuteOffset
= Number(match
[11] || 0),
1055 minute
> 0 || second
> 0 || millisecond
> 0 ?
1058 minute
< 60 && second
< 60 && millisecond
< 1000 &&
1059 month
> -1 && month
< 12 && hourOffset
< 24 &&
1060 minuteOffset
< 60 && // detect invalid offsets
1063 dayFromMonth(year
, month
+ 1) -
1064 dayFromMonth(year
, month
)
1068 (dayFromMonth(year
, month
) + day
) * 24 +
1070 hourOffset
* signOffset
1073 (result
+ minute
+ minuteOffset
* signOffset
) * 60 +
1075 ) * 1000 + millisecond
;
1077 result
= toUTC(result
);
1079 if (-8.64e15
<= result
&& result
<= 8.64e15
) {
1085 return NativeDate
.parse
.apply(this, arguments
);
1090 /*global Date: false */
1094 // http://es5.github.com/#x15.9.4.4
1096 Date
.now
= function now() {
1097 return new Date().getTime();
1107 // http://es5.github.com/#x15.7.4.5
1108 var hasToFixedBugs
= NumberPrototype
.toFixed
&& (
1109 (0.00008).toFixed(3) !== '0.000' ||
1110 (0.9).toFixed(0) !== '1' ||
1111 (1.255).toFixed(2) !== '1.25' ||
1112 (1000000000000000128).toFixed(0) !== '1000000000000000128'
1115 var toFixedHelpers
= {
1118 data
: [0, 0, 0, 0, 0, 0],
1119 multiply
: function multiply(n
, c
) {
1122 while (++i
< toFixedHelpers
.size
) {
1123 c2
+= n
* toFixedHelpers
.data
[i
];
1124 toFixedHelpers
.data
[i
] = c2
% toFixedHelpers
.base
;
1125 c2
= Math
.floor(c2
/ toFixedHelpers
.base
);
1128 divide
: function divide(n
) {
1129 var i
= toFixedHelpers
.size
, c
= 0;
1131 c
+= toFixedHelpers
.data
[i
];
1132 toFixedHelpers
.data
[i
] = Math
.floor(c
/ n
);
1133 c
= (c
% n
) * toFixedHelpers
.base
;
1136 numToString
: function numToString() {
1137 var i
= toFixedHelpers
.size
;
1140 if (s
!== '' || i
=== 0 || toFixedHelpers
.data
[i
] !== 0) {
1141 var t
= String(toFixedHelpers
.data
[i
]);
1145 s
+= '0000000'.slice(0, 7 - t
.length
) + t
;
1151 pow
: function pow(x
, n
, acc
) {
1152 return (n
=== 0 ? acc
: (n
% 2 === 1 ? pow(x
, n
- 1, acc
* x
) : pow(x
* x
, n
/ 2, acc
)));
1154 log
: function log(x
) {
1157 while (x2
>= 4096) {
1169 defineProperties(NumberPrototype
, {
1170 toFixed
: function toFixed(fractionDigits
) {
1171 var f
, x
, s
, m
, e
, z
, j
, k
;
1173 // Test for NaN and round fractionDigits down
1174 f
= Number(fractionDigits
);
1175 f
= f
!== f
? 0 : Math
.floor(f
);
1177 if (f
< 0 || f
> 20) {
1178 throw new RangeError('Number.toFixed called with invalid number of decimals');
1188 // If it is too big or small, return the string value of the number
1189 if (x
<= -1e21
|| x
>= 1e21
) {
1204 // -70 < log2(x) < 70
1205 e
= toFixedHelpers
.log(x
* toFixedHelpers
.pow(2, 69, 1)) - 69;
1206 z
= (e
< 0 ? x
* toFixedHelpers
.pow(2, -e
, 1) : x
/ toFixedHelpers
.pow(2, e
, 1));
1207 z
*= 0x10000000000000; // Math.pow(2, 52);
1213 toFixedHelpers
.multiply(0, z
);
1217 toFixedHelpers
.multiply(1e7
, 0);
1221 toFixedHelpers
.multiply(toFixedHelpers
.pow(10, j
, 1), 0);
1225 toFixedHelpers
.divide(1 << 23);
1229 toFixedHelpers
.divide(1 << j
);
1230 toFixedHelpers
.multiply(1, 1);
1231 toFixedHelpers
.divide(2);
1232 m
= toFixedHelpers
.numToString();
1234 toFixedHelpers
.multiply(0, z
);
1235 toFixedHelpers
.multiply(1 << (-e
), 0);
1236 m
= toFixedHelpers
.numToString() + '0.00000000000000000000'.slice(2, 2 + f
);
1244 m
= s
+ '0.0000000000000000000'.slice(0, f
- k
+ 2) + m
;
1246 m
= s
+ m
.slice(0, k
- f
) + '.' + m
.slice(k
- f
);
1262 // http://es5.github.com/#x15.5.4.14
1264 // [bugfix, IE lt 9, firefox 4, Konqueror, Opera, obscure browsers]
1265 // Many browsers do not split properly with regular expressions or they
1266 // do not perform the split correctly under obscure conditions.
1267 // See http://blog.stevenlevithan.com/archives/cross-browser-split
1268 // I've tested in many browsers and this seems to cover the deviant ones:
1269 // 'ab'.split(/(?:ab)*/) should be ["", ""], not [""]
1270 // '.'.split(/(.?)(.?)/) should be ["", ".", "", ""], not ["", ""]
1271 // 'tesst'.split(/(s)*/) should be ["t", undefined, "e", "s", "t"], not
1272 // [undefined, "t", undefined, "e", ...]
1273 // ''.split(/.?/) should be [], not [""]
1274 // '.'.split(/()()/) should be ["."], not ["", "", "."]
1276 var string_split
= StringPrototype
.split
;
1278 'ab'.split(/(?:ab)*/).length
!== 2 ||
1279 '.'.split(/(.?)(.?)/).length
!== 4 ||
1280 'tesst'.split(/(s)*/)[1] === 't' ||
1281 'test'.split(/(?:)/, -1).length
!== 4 ||
1282 ''.split(/.?/).length
||
1283 '.'.split(/()()/).length
> 1
1286 var compliantExecNpcg
= typeof (/()??/).exec('')[1] === 'undefined'; // NPCG: nonparticipating capturing group
1288 StringPrototype
.split = function (separator
, limit
) {
1290 if (typeof separator
=== 'undefined' && limit
=== 0) {
1294 // If `separator` is not a regex, use native split
1295 if (!isRegex(separator
)) {
1296 return string_split
.call(this, separator
, limit
);
1300 var flags
= (separator
.ignoreCase
? 'i' : '') +
1301 (separator
.multiline
? 'm' : '') +
1302 (separator
.extended
? 'x' : '') + // Proposed for ES6
1303 (separator
.sticky
? 'y' : ''), // Firefox 3+
1305 // Make `global` and avoid `lastIndex` issues by working with a copy
1306 separator2
, match
, lastIndex
, lastLength
;
1307 var separatorCopy
= new RegExp(separator
.source
, flags
+ 'g');
1308 string
+= ''; // Type-convert
1309 if (!compliantExecNpcg
) {
1310 // Doesn't need flags gy, but they don't hurt
1311 separator2
= new RegExp('^' + separatorCopy
.source
+ '$(?!\\s)', flags
);
1313 /* Values for `limit`, per the spec:
1314 * If undefined: 4294967295 // Math.pow(2, 32) - 1
1315 * If 0, Infinity, or NaN: 0
1316 * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
1317 * If negative number: 4294967296 - Math.floor(Math.abs(limit))
1318 * If other: Type-convert, then use the above rules
1320 var splitLimit
= typeof limit
=== 'undefined' ?
1321 -1 >>> 0 : // Math.pow(2, 32) - 1
1323 match
= separatorCopy
.exec(string
);
1325 // `separatorCopy.lastIndex` is not reliable cross-browser
1326 lastIndex
= match
.index
+ match
[0].length
;
1327 if (lastIndex
> lastLastIndex
) {
1328 output
.push(string
.slice(lastLastIndex
, match
.index
));
1329 // Fix browsers whose `exec` methods don't consistently return `undefined` for
1330 // nonparticipating capturing groups
1331 if (!compliantExecNpcg
&& match
.length
> 1) {
1332 /*eslint-disable no-loop-func */
1333 match
[0].replace(separator2
, function () {
1334 for (var i
= 1; i
< arguments
.length
- 2; i
++) {
1335 if (typeof arguments
[i
] === 'undefined') {
1340 /*eslint-enable no-loop-func */
1342 if (match
.length
> 1 && match
.index
< string
.length
) {
1343 array_push
.apply(output
, match
.slice(1));
1345 lastLength
= match
[0].length
;
1346 lastLastIndex
= lastIndex
;
1347 if (output
.length
>= splitLimit
) {
1351 if (separatorCopy
.lastIndex
=== match
.index
) {
1352 separatorCopy
.lastIndex
++; // Avoid an infinite loop
1354 match
= separatorCopy
.exec(string
);
1356 if (lastLastIndex
=== string
.length
) {
1357 if (lastLength
|| !separatorCopy
.test('')) {
1361 output
.push(string
.slice(lastLastIndex
));
1363 return output
.length
> splitLimit
? output
.slice(0, splitLimit
) : output
;
1368 // If separator is undefined, then the result array contains just one String,
1369 // which is the this value (converted to a String). If limit is not undefined,
1370 // then the output array is truncated so that it contains no more than limit
1372 // "0".split(undefined, 0) -> []
1373 } else if ('0'.split(void 0, 0).length
) {
1374 StringPrototype
.split
= function split(separator
, limit
) {
1375 if (typeof separator
=== 'undefined' && limit
=== 0) { return []; }
1376 return string_split
.call(this, separator
, limit
);
1380 var str_replace
= StringPrototype
.replace
;
1381 var replaceReportsGroupsCorrectly
= (function () {
1383 'x'.replace(/x(.)?/g, function (match
, group
) {
1386 return groups
.length
=== 1 && typeof groups
[0] === 'undefined';
1389 if (!replaceReportsGroupsCorrectly
) {
1390 StringPrototype
.replace
= function replace(searchValue
, replaceValue
) {
1391 var isFn
= isCallable(replaceValue
);
1392 var hasCapturingGroups
= isRegex(searchValue
) && (/\)[*?]/).test(searchValue
.source
);
1393 if (!isFn
|| !hasCapturingGroups
) {
1394 return str_replace
.call(this, searchValue
, replaceValue
);
1396 var wrappedReplaceValue = function (match
) {
1397 var length
= arguments
.length
;
1398 var originalLastIndex
= searchValue
.lastIndex
;
1399 searchValue
.lastIndex
= 0;
1400 var args
= searchValue
.exec(match
) || [];
1401 searchValue
.lastIndex
= originalLastIndex
;
1402 args
.push(arguments
[length
- 2], arguments
[length
- 1]);
1403 return replaceValue
.apply(this, args
);
1405 return str_replace
.call(this, searchValue
, wrappedReplaceValue
);
1410 // ECMA-262, 3rd B.2.3
1411 // Not an ECMAScript standard, although ECMAScript 3rd Edition has a
1412 // non-normative section suggesting uniform semantics and it should be
1413 // normalized across all browsers
1414 // [bugfix, IE lt 9] IE < 9 substr() with negative value not working in IE
1415 var string_substr
= StringPrototype
.substr
;
1416 var hasNegativeSubstrBug
= ''.substr
&& '0b'.substr(-1) !== 'b';
1417 defineProperties(StringPrototype
, {
1418 substr
: function substr(start
, length
) {
1419 var normalizedStart
= start
;
1421 normalizedStart
= Math
.max(this.length
+ start
, 0);
1423 return string_substr
.call(this, normalizedStart
, length
);
1425 }, hasNegativeSubstrBug
);
1428 // whitespace from: http://es5.github.io/#x15.5.4.20
1429 var ws
= '\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003' +
1430 '\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028' +
1432 var zeroWidth
= '\u200b';
1433 var wsRegexChars
= '[' + ws
+ ']';
1434 var trimBeginRegexp
= new RegExp('^' + wsRegexChars
+ wsRegexChars
+ '*');
1435 var trimEndRegexp
= new RegExp(wsRegexChars
+ wsRegexChars
+ '*$');
1436 var hasTrimWhitespaceBug
= StringPrototype
.trim
&& (ws
.trim() || !zeroWidth
.trim());
1437 defineProperties(StringPrototype
, {
1438 // http://blog.stevenlevithan.com/archives/faster-trim-javascript
1439 // http://perfectionkills.com/whitespace-deviations/
1440 trim
: function trim() {
1441 if (typeof this === 'undefined' || this === null) {
1442 throw new TypeError("can't convert " + this + ' to object');
1444 return String(this).replace(trimBeginRegexp
, '').replace(trimEndRegexp
, '');
1446 }, hasTrimWhitespaceBug
);
1449 if (parseInt(ws
+ '08') !== 8 || parseInt(ws
+ '0x16') !== 22) {
1450 /*global parseInt: true */
1451 parseInt
= (function (origParseInt
) {
1452 var hexRegex
= /^0[xX]/;
1453 return function parseInt(str
, radix
) {
1454 var string
= String(str
).trim();
1455 var defaultedRadix
= Number(radix
) || (hexRegex
.test(string
) ? 16 : 10);
1456 return origParseInt(string
, defaultedRadix
);