2 * https://github.com/es-shims/es5-shim
3 * @license es5-shim Copyright 2009-2014 by contributors, MIT License
4 * see https://github.com/es-shims/es5-shim/blob/master/LICENSE
7 // vim: ts=4 sts=4 sw=4 expandtab
9 //Add semicolon to prevent IIFE from being passed as argument to concated code.
12 // UMD (Universal Module Definition)
13 // see https://github.com/umdjs/umd/blob/master/returnExports.js
14 (function (root
, factory
) {
15 if (typeof define
=== 'function' && define
.amd
) {
16 // AMD. Register as an anonymous module.
18 } else if (typeof exports
=== 'object') {
19 // Node. Does not work with strict CommonJS, but
20 // only CommonJS-like enviroments that support module.exports,
22 module
.exports
= factory();
24 // Browser globals (root is window)
25 root
.returnExports
= factory();
30 * Brings an environment as close to ECMAScript 5 compliance
31 * as is possible with the facilities of erstwhile engines.
33 * Annotated ES5: http://es5.github.com/ (specific links below)
34 * ES5 Spec: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
35 * Required reading: http://javascriptweblog.wordpress.com/2011/12/05/extending-javascript-natives/
38 // Shortcut to an often accessed properties, in order to avoid multiple
39 // dereference that costs universally.
40 var ArrayPrototype
= Array
.prototype;
41 var ObjectPrototype
= Object
.prototype;
42 var FunctionPrototype
= Function
.prototype;
43 var StringPrototype
= String
.prototype;
44 var NumberPrototype
= Number
.prototype;
45 var _Array_slice_
= ArrayPrototype
.slice
;
46 var array_splice
= ArrayPrototype
.splice
;
47 var array_push
= ArrayPrototype
.push
;
48 var array_unshift
= ArrayPrototype
.unshift
;
49 var call
= FunctionPrototype
.call
;
51 // Having a toString local variable name breaks in Opera so use _toString.
52 var _toString
= ObjectPrototype
.toString
;
54 var isFunction = function (val
) {
55 return ObjectPrototype
.toString
.call(val
) === '[object Function]';
57 var isRegex = function (val
) {
58 return ObjectPrototype
.toString
.call(val
) === '[object RegExp]';
60 var isArray
= function isArray(obj
) {
61 return _toString
.call(obj
) === "[object Array]";
63 var isString
= function isString(obj
) {
64 return _toString
.call(obj
) === "[object String]";
66 var isArguments
= function isArguments(value
) {
67 var str
= _toString
.call(value
);
68 var isArgs
= str
=== '[object Arguments]';
70 isArgs
= !isArray(str
)
72 && typeof value
=== 'object'
73 && typeof value
.length
=== 'number'
75 && isFunction(value
.callee
);
80 var supportsDescriptors
= Object
.defineProperty
&& (function () {
82 Object
.defineProperty({}, 'x', {});
84 } catch (e
) { /* this is ES3 */
89 // Define configurable, writable and non-enumerable props
90 // if they don't exist.
92 if (supportsDescriptors
) {
93 defineProperty = function (object
, name
, method
, forceAssign
) {
94 if (!forceAssign
&& (name
in object
)) { return; }
95 Object
.defineProperty(object
, name
, {
103 defineProperty = function (object
, name
, method
, forceAssign
) {
104 if (!forceAssign
&& (name
in object
)) { return; }
105 object
[name
] = method
;
108 var defineProperties = function (object
, map
, forceAssign
) {
109 for (var name
in map
) {
110 if (ObjectPrototype
.hasOwnProperty
.call(map
, name
)) {
111 defineProperty(object
, name
, map
[name
], forceAssign
);
122 // http://es5.github.com/#x9.4
123 // http://jsperf.com/to-integer
125 function toInteger(n
) {
127 if (n
!== n
) { // isNaN
129 } else if (n
!== 0 && n
!== (1 / 0) && n
!== -(1 / 0)) {
130 n
= (n
> 0 || -1) * Math
.floor(Math
.abs(n
));
135 function isPrimitive(input
) {
136 var type
= typeof input
;
139 type
=== "undefined" ||
140 type
=== "boolean" ||
146 function toPrimitive(input
) {
147 var val
, valueOf
, toStr
;
148 if (isPrimitive(input
)) {
151 valueOf
= input
.valueOf
;
152 if (isFunction(valueOf
)) {
153 val
= valueOf
.call(input
);
154 if (isPrimitive(val
)) {
158 toStr
= input
.toString
;
159 if (isFunction(toStr
)) {
160 val
= toStr
.call(input
);
161 if (isPrimitive(val
)) {
165 throw new TypeError();
169 // http://es5.github.com/#x9.9
170 var toObject = function (o
) {
171 if (o
== null) { // this matches both null and undefined
172 throw new TypeError("can't convert " + o
+ " to object");
177 var ToUint32
= function ToUint32(x
) {
187 // http://es5.github.com/#x15.3.4.5
191 defineProperties(FunctionPrototype
, {
192 bind
: function bind(that
) { // .length is 1
193 // 1. Let Target be the this value.
195 // 2. If IsCallable(Target) is false, throw a TypeError exception.
196 if (!isFunction(target
)) {
197 throw new TypeError("Function.prototype.bind called on incompatible " + target
);
199 // 3. Let A be a new (possibly empty) internal list of all of the
200 // argument values provided after thisArg (arg1, arg2 etc), in order.
201 // XXX slicedArgs will stand in for "A" if used
202 var args
= _Array_slice_
.call(arguments
, 1); // for normal call
203 // 4. Let F be a new native ECMAScript object.
204 // 11. Set the [[Prototype]] internal property of F to the standard
205 // built-in Function prototype object as specified in 15.3.3.1.
206 // 12. Set the [[Call]] internal property of F as described in
208 // 13. Set the [[Construct]] internal property of F as described in
210 // 14. Set the [[HasInstance]] internal property of F as described in
212 var binder = function () {
214 if (this instanceof bound
) {
215 // 15.3.4.5.2 [[Construct]]
216 // When the [[Construct]] internal method of a function object,
217 // F that was created using the bind function is called with a
218 // list of arguments ExtraArgs, the following steps are taken:
219 // 1. Let target be the value of F's [[TargetFunction]]
220 // internal property.
221 // 2. If target has no [[Construct]] internal method, a
222 // TypeError exception is thrown.
223 // 3. Let boundArgs be the value of F's [[BoundArgs]] internal
225 // 4. Let args be a new list containing the same values as the
226 // list boundArgs in the same order followed by the same
227 // values as the list ExtraArgs in the same order.
228 // 5. Return the result of calling the [[Construct]] internal
229 // method of target providing args as the arguments.
231 var result
= target
.apply(
233 args
.concat(_Array_slice_
.call(arguments
))
235 if (Object(result
) === result
) {
241 // 15.3.4.5.1 [[Call]]
242 // When the [[Call]] internal method of a function object, F,
243 // which was created using the bind function is called with a
244 // this value and a list of arguments ExtraArgs, the following
246 // 1. Let boundArgs be the value of F's [[BoundArgs]] internal
248 // 2. Let boundThis be the value of F's [[BoundThis]] internal
250 // 3. Let target be the value of F's [[TargetFunction]] internal
252 // 4. Let args be a new list containing the same values as the
253 // list boundArgs in the same order followed by the same
254 // values as the list ExtraArgs in the same order.
255 // 5. Return the result of calling the [[Call]] internal method
256 // of target providing boundThis as the this value and
257 // providing args as the arguments.
259 // equiv: target.call(this, ...boundArgs, ...args)
262 args
.concat(_Array_slice_
.call(arguments
))
269 // 15. If the [[Class]] internal property of Target is "Function", then
270 // a. Let L be the length property of Target minus the length of A.
271 // b. Set the length own property of F to either 0 or L, whichever is
273 // 16. Else set the length own property of F to 0.
275 var boundLength
= Math
.max(0, target
.length
- args
.length
);
277 // 17. Set the attributes of the length own property of F to the values
278 // specified in 15.3.5.1.
280 for (var i
= 0; i
< boundLength
; i
++) {
281 boundArgs
.push("$" + i
);
284 // XXX Build a dynamic function with desired amount of arguments is the only
285 // way to set the length property of a function.
286 // In environments where Content Security Policies enabled (Chrome extensions,
287 // for ex.) all use of eval or Function costructor throws an exception.
288 // However in all of these environments Function.prototype.bind exists
289 // and so this code will never be executed.
290 var bound
= Function("binder", "return function (" + boundArgs
.join(",") + "){return binder.apply(this,arguments)}")(binder
);
292 if (target
.prototype) {
293 Empty
.prototype = target
.prototype;
294 bound
.prototype = new Empty();
295 // Clean up dangling references.
296 Empty
.prototype = null;
300 // 18. Set the [[Extensible]] internal property of F to true.
303 // 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3).
304 // 20. Call the [[DefineOwnProperty]] internal method of F with
305 // arguments "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]:
306 // thrower, [[Enumerable]]: false, [[Configurable]]: false}, and
308 // 21. Call the [[DefineOwnProperty]] internal method of F with
309 // arguments "arguments", PropertyDescriptor {[[Get]]: thrower,
310 // [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false},
314 // NOTE Function objects created using Function.prototype.bind do not
315 // have a prototype property or the [[Code]], [[FormalParameters]], and
316 // [[Scope]] internal properties.
317 // XXX can't delete prototype in pure-js.
324 // _Please note: Shortcuts are defined after `Function.prototype.bind` as we
325 // us it in defining shortcuts.
326 var owns
= call
.bind(ObjectPrototype
.hasOwnProperty
);
328 // If JS engine supports accessors creating shortcuts.
333 var supportsAccessors
;
334 if ((supportsAccessors
= owns(ObjectPrototype
, "__defineGetter__"))) {
335 defineGetter
= call
.bind(ObjectPrototype
.__defineGetter__
);
336 defineSetter
= call
.bind(ObjectPrototype
.__defineSetter__
);
337 lookupGetter
= call
.bind(ObjectPrototype
.__lookupGetter__
);
338 lookupSetter
= call
.bind(ObjectPrototype
.__lookupSetter__
);
347 // http://es5.github.com/#x15.4.4.12
348 var spliceNoopReturnsEmptyArray
= (function () {
350 var result
= a
.splice();
351 return a
.length
=== 2 && isArray(result
) && result
.length
=== 0;
353 defineProperties(ArrayPrototype
, {
354 // Safari 5.0 bug where .splice() returns undefined
355 splice
: function splice(start
, deleteCount
) {
356 if (arguments
.length
=== 0) {
359 return array_splice
.apply(this, arguments
);
362 }, spliceNoopReturnsEmptyArray
);
364 var spliceWorksWithEmptyObject
= (function () {
366 ArrayPrototype
.splice
.call(obj
, 0, 0, 1);
367 return obj
.length
=== 1;
369 var omittingSecondSpliceArgIsNoop
= [1].splice(0).length
=== 0;
370 defineProperties(ArrayPrototype
, {
371 splice
: function splice(start
, deleteCount
) {
372 if (arguments
.length
=== 0) { return []; }
373 var args
= arguments
;
374 this.length
= Math
.max(toInteger(this.length
), 0);
375 if (arguments
.length
> 0 && typeof deleteCount
!== 'number') {
376 args
= _Array_slice_
.call(arguments
);
377 if (args
.length
< 2) {
378 args
.push(toInteger(deleteCount
));
380 args
[1] = toInteger(deleteCount
);
383 return array_splice
.apply(this, args
);
385 }, !omittingSecondSpliceArgIsNoop
|| !spliceWorksWithEmptyObject
);
388 // http://es5.github.com/#x15.4.4.13
389 // Return len+argCount.
391 // IE < 8 bug: [].unshift(0) === undefined but should be "1"
392 var hasUnshiftReturnValueBug
= [].unshift(0) !== 1;
393 defineProperties(ArrayPrototype
, {
394 unshift: function () {
395 array_unshift
.apply(this, arguments
);
398 }, hasUnshiftReturnValueBug
);
401 // http://es5.github.com/#x15.4.3.2
402 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray
403 defineProperties(Array
, { isArray
: isArray
});
405 // The IsCallable() check in the Array functions
406 // has been replaced with a strict check on the
407 // internal class of the object to trap cases where
408 // the provided function was actually a regular
409 // expression literal, which in V8 and
410 // JavaScriptCore is a typeof "function". Only in
411 // V8 are regular expression literals permitted as
412 // reduce parameters, so it is desirable in the
413 // general case for the shim to match the more
414 // strict and common behavior of rejecting regular
418 // http://es5.github.com/#x15.4.4.18
419 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/forEach
421 // Check failure of by-index access of string characters (IE < 9)
422 // and failure of `0 in boxedString` (Rhino)
423 var boxedString
= Object("a");
424 var splitString
= boxedString
[0] !== "a" || !(0 in boxedString
);
426 var properlyBoxesContext
= function properlyBoxed(method
) {
427 // Check node 0.6.21 bug where third parameter is not boxed
428 var properlyBoxesNonStrict
= true;
429 var properlyBoxesStrict
= true;
431 method
.call('foo', function (_
, __
, context
) {
432 if (typeof context
!== 'object') { properlyBoxesNonStrict
= false; }
435 method
.call([1], function () {
437 properlyBoxesStrict
= typeof this === 'string';
440 return !!method
&& properlyBoxesNonStrict
&& properlyBoxesStrict
;
443 defineProperties(ArrayPrototype
, {
444 forEach
: function forEach(fun
/*, thisp*/) {
445 var object
= toObject(this),
446 self
= splitString
&& isString(this) ? this.split('') : object
,
447 thisp
= arguments
[1],
449 length
= self
.length
>>> 0;
451 // If no callback function or if callback is not a callable function
452 if (!isFunction(fun
)) {
453 throw new TypeError(); // TODO message
456 while (++i
< length
) {
458 // Invoke the callback function with call, passing arguments:
459 // context, property value, property key, thisArg object
461 fun
.call(thisp
, self
[i
], i
, object
);
465 }, !properlyBoxesContext(ArrayPrototype
.forEach
));
468 // http://es5.github.com/#x15.4.4.19
469 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map
470 defineProperties(ArrayPrototype
, {
471 map
: function map(fun
/*, thisp*/) {
472 var object
= toObject(this),
473 self
= splitString
&& isString(this) ? this.split('') : object
,
474 length
= self
.length
>>> 0,
475 result
= Array(length
),
476 thisp
= arguments
[1];
478 // If no callback function or if callback is not a callable function
479 if (!isFunction(fun
)) {
480 throw new TypeError(fun
+ " is not a function");
483 for (var i
= 0; i
< length
; i
++) {
485 result
[i
] = fun
.call(thisp
, self
[i
], i
, object
);
490 }, !properlyBoxesContext(ArrayPrototype
.map
));
493 // http://es5.github.com/#x15.4.4.20
494 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter
495 defineProperties(ArrayPrototype
, {
496 filter
: function filter(fun
/*, thisp */) {
497 var object
= toObject(this),
498 self
= splitString
&& isString(this) ? this.split('') : object
,
499 length
= self
.length
>>> 0,
502 thisp
= arguments
[1];
504 // If no callback function or if callback is not a callable function
505 if (!isFunction(fun
)) {
506 throw new TypeError(fun
+ " is not a function");
509 for (var i
= 0; i
< length
; i
++) {
512 if (fun
.call(thisp
, value
, i
, object
)) {
519 }, !properlyBoxesContext(ArrayPrototype
.filter
));
522 // http://es5.github.com/#x15.4.4.16
523 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every
524 defineProperties(ArrayPrototype
, {
525 every
: function every(fun
/*, thisp */) {
526 var object
= toObject(this),
527 self
= splitString
&& isString(this) ? this.split('') : object
,
528 length
= self
.length
>>> 0,
529 thisp
= arguments
[1];
531 // If no callback function or if callback is not a callable function
532 if (!isFunction(fun
)) {
533 throw new TypeError(fun
+ " is not a function");
536 for (var i
= 0; i
< length
; i
++) {
537 if (i
in self
&& !fun
.call(thisp
, self
[i
], i
, object
)) {
543 }, !properlyBoxesContext(ArrayPrototype
.every
));
546 // http://es5.github.com/#x15.4.4.17
547 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some
548 defineProperties(ArrayPrototype
, {
549 some
: function some(fun
/*, thisp */) {
550 var object
= toObject(this),
551 self
= splitString
&& isString(this) ? this.split('') : object
,
552 length
= self
.length
>>> 0,
553 thisp
= arguments
[1];
555 // If no callback function or if callback is not a callable function
556 if (!isFunction(fun
)) {
557 throw new TypeError(fun
+ " is not a function");
560 for (var i
= 0; i
< length
; i
++) {
561 if (i
in self
&& fun
.call(thisp
, self
[i
], i
, object
)) {
567 }, !properlyBoxesContext(ArrayPrototype
.some
));
570 // http://es5.github.com/#x15.4.4.21
571 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce
572 var reduceCoercesToObject
= false;
573 if (ArrayPrototype
.reduce
) {
574 reduceCoercesToObject
= typeof ArrayPrototype
.reduce
.call('es5', function (_
, __
, ___
, list
) { return list
; }) === 'object';
576 defineProperties(ArrayPrototype
, {
577 reduce
: function reduce(fun
/*, initial*/) {
578 var object
= toObject(this),
579 self
= splitString
&& isString(this) ? this.split('') : object
,
580 length
= self
.length
>>> 0;
582 // If no callback function or if callback is not a callable function
583 if (!isFunction(fun
)) {
584 throw new TypeError(fun
+ " is not a function");
587 // no value to return if no initial value and an empty array
588 if (!length
&& arguments
.length
=== 1) {
589 throw new TypeError("reduce of empty array with no initial value");
594 if (arguments
.length
>= 2) {
595 result
= arguments
[1];
603 // if array contains no values, no initial value to return
605 throw new TypeError("reduce of empty array with no initial value");
610 for (; i
< length
; i
++) {
612 result
= fun
.call(void 0, result
, self
[i
], i
, object
);
618 }, !reduceCoercesToObject
);
621 // http://es5.github.com/#x15.4.4.22
622 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight
623 var reduceRightCoercesToObject
= false;
624 if (ArrayPrototype
.reduceRight
) {
625 reduceRightCoercesToObject
= typeof ArrayPrototype
.reduceRight
.call('es5', function (_
, __
, ___
, list
) { return list
; }) === 'object';
627 defineProperties(ArrayPrototype
, {
628 reduceRight
: function reduceRight(fun
/*, initial*/) {
629 var object
= toObject(this),
630 self
= splitString
&& isString(this) ? this.split('') : object
,
631 length
= self
.length
>>> 0;
633 // If no callback function or if callback is not a callable function
634 if (!isFunction(fun
)) {
635 throw new TypeError(fun
+ " is not a function");
638 // no value to return if no initial value, empty array
639 if (!length
&& arguments
.length
=== 1) {
640 throw new TypeError("reduceRight of empty array with no initial value");
643 var result
, i
= length
- 1;
644 if (arguments
.length
>= 2) {
645 result
= arguments
[1];
653 // if array contains no values, no initial value to return
655 throw new TypeError("reduceRight of empty array with no initial value");
666 result
= fun
.call(void 0, result
, self
[i
], i
, object
);
672 }, !reduceRightCoercesToObject
);
675 // http://es5.github.com/#x15.4.4.14
676 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
677 var hasFirefox2IndexOfBug
= [0, 1].indexOf(1, 2) !== -1;
678 defineProperties(ArrayPrototype
, {
679 indexOf
: function indexOf(sought
/*, fromIndex */ ) {
680 var self
= splitString
&& isString(this) ? this.split('') : toObject(this),
681 length
= self
.length
>>> 0;
688 if (arguments
.length
> 1) {
689 i
= toInteger(arguments
[1]);
692 // handle negative indices
693 i
= i
>= 0 ? i
: Math
.max(0, length
+ i
);
694 for (; i
< length
; i
++) {
695 if (i
in self
&& self
[i
] === sought
) {
701 }, hasFirefox2IndexOfBug
);
704 // http://es5.github.com/#x15.4.4.15
705 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf
706 var hasFirefox2LastIndexOfBug
= [0, 1].lastIndexOf(0, -3) !== -1;
707 defineProperties(ArrayPrototype
, {
708 lastIndexOf
: function lastIndexOf(sought
/*, fromIndex */) {
709 var self
= splitString
&& isString(this) ? this.split('') : toObject(this),
710 length
= self
.length
>>> 0;
716 if (arguments
.length
> 1) {
717 i
= Math
.min(i
, toInteger(arguments
[1]));
719 // handle negative indices
720 i
= i
>= 0 ? i
: length
- Math
.abs(i
);
721 for (; i
>= 0; i
--) {
722 if (i
in self
&& sought
=== self
[i
]) {
728 }, hasFirefox2LastIndexOfBug
);
736 // http://es5.github.com/#x15.2.3.14
738 // http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation
739 var hasDontEnumBug
= !({'toString': null}).propertyIsEnumerable('toString'),
740 hasProtoEnumBug
= (function () {}).propertyIsEnumerable('prototype'),
747 "propertyIsEnumerable",
750 dontEnumsLength
= dontEnums
.length
;
752 defineProperties(Object
, {
753 keys
: function keys(object
) {
754 var isFn
= isFunction(object
),
755 isArgs
= isArguments(object
),
756 isObject
= object
!== null && typeof object
=== 'object',
757 isStr
= isObject
&& isString(object
);
759 if (!isObject
&& !isFn
&& !isArgs
) {
760 throw new TypeError("Object.keys called on a non-object");
764 var skipProto
= hasProtoEnumBug
&& isFn
;
765 if (isStr
|| isArgs
) {
766 for (var i
= 0; i
< object
.length
; ++i
) {
767 theKeys
.push(String(i
));
770 for (var name
in object
) {
771 if (!(skipProto
&& name
=== 'prototype') && owns(object
, name
)) {
772 theKeys
.push(String(name
));
777 if (hasDontEnumBug
) {
778 var ctor
= object
.constructor,
779 skipConstructor
= ctor
&& ctor
.prototype === object
;
780 for (var j
= 0; j
< dontEnumsLength
; j
++) {
781 var dontEnum
= dontEnums
[j
];
782 if (!(skipConstructor
&& dontEnum
=== 'constructor') && owns(object
, dontEnum
)) {
783 theKeys
.push(dontEnum
);
791 var keysWorksWithArguments
= Object
.keys
&& (function () {
793 return Object
.keys(arguments
).length
=== 2;
795 var originalKeys
= Object
.keys
;
796 defineProperties(Object
, {
797 keys
: function keys(object
) {
798 if (isArguments(object
)) {
799 return originalKeys(ArrayPrototype
.slice
.call(object
));
801 return originalKeys(object
);
804 }, !keysWorksWithArguments
);
812 // http://es5.github.com/#x15.9.5.43
813 // This function returns a String value represent the instance in time
814 // represented by this Date object. The format of the String is the Date Time
815 // string format defined in 15.9.1.15. All fields are present in the String.
816 // The time zone is always UTC, denoted by the suffix Z. If the time value of
817 // this object is not a finite Number a RangeError exception is thrown.
818 var negativeDate
= -62198755200000;
819 var negativeYearString
= "-000001";
820 var hasNegativeDateBug
= Date
.prototype.toISOString
&& new Date(negativeDate
).toISOString().indexOf(negativeYearString
) === -1;
822 defineProperties(Date
.prototype, {
823 toISOString
: function toISOString() {
824 var result
, length
, value
, year
, month
;
825 if (!isFinite(this)) {
826 throw new RangeError("Date.prototype.toISOString called on non-finite value.");
829 year
= this.getUTCFullYear();
831 month
= this.getUTCMonth();
832 // see https://github.com/es-shims/es5-shim/issues/111
833 year
+= Math
.floor(month
/ 12);
834 month
= (month
% 12 + 12) % 12;
836 // the date time string format is specified in 15.9.1.15.
837 result
= [month
+ 1, this.getUTCDate(), this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds()];
839 (year
< 0 ? "-" : (year
> 9999 ? "+" : "")) +
840 ("00000" + Math
.abs(year
)).slice(0 <= year
&& year
<= 9999 ? -4 : -6)
843 length
= result
.length
;
845 value
= result
[length
];
846 // pad months, days, hours, minutes, and seconds to have two
849 result
[length
] = "0" + value
;
852 // pad milliseconds to have three digits.
854 year
+ "-" + result
.slice(0, 2).join("-") +
855 "T" + result
.slice(2).join(":") + "." +
856 ("000" + this.getUTCMilliseconds()).slice(-3) + "Z"
859 }, hasNegativeDateBug
);
863 // http://es5.github.com/#x15.9.5.44
864 // This function provides a String representation of a Date object for use by
865 // JSON.stringify (15.12.3).
866 var dateToJSONIsSupported
= false;
868 dateToJSONIsSupported
= (
869 Date
.prototype.toJSON
&&
870 new Date(NaN
).toJSON() === null &&
871 new Date(negativeDate
).toJSON().indexOf(negativeYearString
) !== -1 &&
872 Date
.prototype.toJSON
.call({ // generic
873 toISOString: function () {
880 if (!dateToJSONIsSupported
) {
881 Date
.prototype.toJSON
= function toJSON(key
) {
882 // When the toJSON method is called with argument key, the following
885 // 1. Let O be the result of calling ToObject, giving it the this
886 // value as its argument.
887 // 2. Let tv be toPrimitive(O, hint Number).
888 var o
= Object(this),
891 // 3. If tv is a Number and is not finite, return null.
892 if (typeof tv
=== "number" && !isFinite(tv
)) {
895 // 4. Let toISO be the result of calling the [[Get]] internal method of
896 // O with argument "toISOString".
897 toISO
= o
.toISOString
;
898 // 5. If IsCallable(toISO) is false, throw a TypeError exception.
899 if (typeof toISO
!== "function") {
900 throw new TypeError("toISOString property is not callable");
902 // 6. Return the result of calling the [[Call]] internal method of
903 // toISO with O as the this value and an empty argument list.
904 return toISO
.call(o
);
906 // NOTE 1 The argument is ignored.
908 // NOTE 2 The toJSON function is intentionally generic; it does not
909 // require that its this value be a Date object. Therefore, it can be
910 // transferred to other kinds of objects for use as a method. However,
911 // it does require that any such object have a toISOString method. An
912 // object is free to use the argument key to filter its
918 // http://es5.github.com/#x15.9.4.2
919 // based on work shared by Daniel Friesen (dantman)
920 // http://gist.github.com/303249
921 var supportsExtendedYears
= Date
.parse('+033658-09-27T01:46:40.000Z') === 1e15
;
922 var acceptsInvalidDates
= !isNaN(Date
.parse('2012-04-04T24:00:00.500Z')) || !isNaN(Date
.parse('2012-11-31T23:59:59.000Z'));
923 var doesNotParseY2KNewYear
= isNaN(Date
.parse("2000-01-01T00:00:00.000Z"));
924 if (!Date
.parse
|| doesNotParseY2KNewYear
|| acceptsInvalidDates
|| !supportsExtendedYears
) {
925 // XXX global assignment won't work in embeddings that use
926 // an alternate object for the context.
927 Date
= (function (NativeDate
) {
930 function Date(Y
, M
, D
, h
, m
, s
, ms
) {
931 var length
= arguments
.length
;
932 if (this instanceof NativeDate
) {
933 var date
= length
=== 1 && String(Y
) === Y
? // isString(Y)
934 // We explicitly pass it through parse:
935 new NativeDate(Date
.parse(Y
)) :
936 // We have to manually make calls depending on argument
938 length
>= 7 ? new NativeDate(Y
, M
, D
, h
, m
, s
, ms
) :
939 length
>= 6 ? new NativeDate(Y
, M
, D
, h
, m
, s
) :
940 length
>= 5 ? new NativeDate(Y
, M
, D
, h
, m
) :
941 length
>= 4 ? new NativeDate(Y
, M
, D
, h
) :
942 length
>= 3 ? new NativeDate(Y
, M
, D
) :
943 length
>= 2 ? new NativeDate(Y
, M
) :
944 length
>= 1 ? new NativeDate(Y
) :
946 // Prevent mixups with unfixed Date object
947 date
.constructor = Date
;
950 return NativeDate
.apply(this, arguments
);
953 // 15.9.1.15 Date Time String Format.
954 var isoDateExpression
= new RegExp("^" +
955 "(\\d{4}|[\+\-]\\d{6})" + // four-digit year capture or sign +
956 // 6-digit extended year
957 "(?:-(\\d{2})" + // optional month capture
958 "(?:-(\\d{2})" + // optional day capture
959 "(?:" + // capture hours:minutes:seconds.milliseconds
960 "T(\\d{2})" + // hours capture
961 ":(\\d{2})" + // minutes capture
962 "(?:" + // optional :seconds.milliseconds
963 ":(\\d{2})" + // seconds capture
964 "(?:(\\.\\d{1,}))?" + // milliseconds capture
966 "(" + // capture UTC offset component
967 "Z|" + // UTC capture
968 "(?:" + // offset specifier +/-hours:minutes
969 "([-+])" + // sign capture
970 "(\\d{2})" + // hours offset capture
971 ":(\\d{2})" + // minutes offset capture
977 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
980 function dayFromMonth(year
, month
) {
981 var t
= month
> 1 ? 1 : 0;
984 Math
.floor((year
- 1969 + t
) / 4) -
985 Math
.floor((year
- 1901 + t
) / 100) +
986 Math
.floor((year
- 1601 + t
) / 400) +
992 return Number(new NativeDate(1970, 0, 1, 0, 0, 0, t
));
995 // Copy any custom methods a 3rd party library may have added
996 for (var key
in NativeDate
) {
997 Date
[key
] = NativeDate
[key
];
1000 // Copy "native" methods explicitly; they may be non-enumerable
1001 Date
.now
= NativeDate
.now
;
1002 Date
.UTC
= NativeDate
.UTC
;
1003 Date
.prototype = NativeDate
.prototype;
1004 Date
.prototype.constructor = Date
;
1006 // Upgrade Date.parse to handle simplified ISO 8601 strings
1007 Date
.parse
= function parse(string
) {
1008 var match
= isoDateExpression
.exec(string
);
1010 // parse months, days, hours, minutes, seconds, and milliseconds
1011 // provide default values if necessary
1012 // parse the UTC offset component
1013 var year
= Number(match
[1]),
1014 month
= Number(match
[2] || 1) - 1,
1015 day
= Number(match
[3] || 1) - 1,
1016 hour
= Number(match
[4] || 0),
1017 minute
= Number(match
[5] || 0),
1018 second
= Number(match
[6] || 0),
1019 millisecond
= Math
.floor(Number(match
[7] || 0) * 1000),
1020 // When time zone is missed, local offset should be used
1022 // see https://bugs.ecmascript.org/show_bug.cgi?id=112
1023 isLocalTime
= Boolean(match
[4] && !match
[8]),
1024 signOffset
= match
[9] === "-" ? 1 : -1,
1025 hourOffset
= Number(match
[10] || 0),
1026 minuteOffset
= Number(match
[11] || 0),
1030 minute
> 0 || second
> 0 || millisecond
> 0 ?
1033 minute
< 60 && second
< 60 && millisecond
< 1000 &&
1034 month
> -1 && month
< 12 && hourOffset
< 24 &&
1035 minuteOffset
< 60 && // detect invalid offsets
1038 dayFromMonth(year
, month
+ 1) -
1039 dayFromMonth(year
, month
)
1043 (dayFromMonth(year
, month
) + day
) * 24 +
1045 hourOffset
* signOffset
1048 (result
+ minute
+ minuteOffset
* signOffset
) * 60 +
1050 ) * 1000 + millisecond
;
1052 result
= toUTC(result
);
1054 if (-8.64e15
<= result
&& result
<= 8.64e15
) {
1060 return NativeDate
.parse
.apply(this, arguments
);
1068 // http://es5.github.com/#x15.9.4.4
1070 Date
.now
= function now() {
1071 return new Date().getTime();
1082 // http://es5.github.com/#x15.7.4.5
1083 var hasToFixedBugs
= NumberPrototype
.toFixed
&& (
1084 (0.00008).toFixed(3) !== '0.000'
1085 || (0.9).toFixed(0) === '0'
1086 || (1.255).toFixed(2) !== '1.25'
1087 || (1000000000000000128).toFixed(0) !== "1000000000000000128"
1090 var toFixedHelpers
= {
1093 data
: [0, 0, 0, 0, 0, 0],
1094 multiply
: function multiply(n
, c
) {
1096 while (++i
< toFixedHelpers
.size
) {
1097 c
+= n
* toFixedHelpers
.data
[i
];
1098 toFixedHelpers
.data
[i
] = c
% toFixedHelpers
.base
;
1099 c
= Math
.floor(c
/ toFixedHelpers
.base
);
1102 divide
: function divide(n
) {
1103 var i
= toFixedHelpers
.size
, c
= 0;
1105 c
+= toFixedHelpers
.data
[i
];
1106 toFixedHelpers
.data
[i
] = Math
.floor(c
/ n
);
1107 c
= (c
% n
) * toFixedHelpers
.base
;
1110 numToString
: function numToString() {
1111 var i
= toFixedHelpers
.size
;
1114 if (s
!== '' || i
=== 0 || toFixedHelpers
.data
[i
] !== 0) {
1115 var t
= String(toFixedHelpers
.data
[i
]);
1119 s
+= '0000000'.slice(0, 7 - t
.length
) + t
;
1125 pow
: function pow(x
, n
, acc
) {
1126 return (n
=== 0 ? acc
: (n
% 2 === 1 ? pow(x
, n
- 1, acc
* x
) : pow(x
* x
, n
/ 2, acc
)));
1128 log
: function log(x
) {
1142 defineProperties(NumberPrototype
, {
1143 toFixed
: function toFixed(fractionDigits
) {
1144 var f
, x
, s
, m
, e
, z
, j
, k
;
1146 // Test for NaN and round fractionDigits down
1147 f
= Number(fractionDigits
);
1148 f
= f
!== f
? 0 : Math
.floor(f
);
1150 if (f
< 0 || f
> 20) {
1151 throw new RangeError("Number.toFixed called with invalid number of decimals");
1161 // If it is too big or small, return the string value of the number
1162 if (x
<= -1e21
|| x
>= 1e21
) {
1177 // -70 < log2(x) < 70
1178 e
= toFixedHelpers
.log(x
* toFixedHelpers
.pow(2, 69, 1)) - 69;
1179 z
= (e
< 0 ? x
* toFixedHelpers
.pow(2, -e
, 1) : x
/ toFixedHelpers
.pow(2, e
, 1));
1180 z
*= 0x10000000000000; // Math.pow(2, 52);
1186 toFixedHelpers
.multiply(0, z
);
1190 toFixedHelpers
.multiply(1e7
, 0);
1194 toFixedHelpers
.multiply(toFixedHelpers
.pow(10, j
, 1), 0);
1198 toFixedHelpers
.divide(1 << 23);
1202 toFixedHelpers
.divide(1 << j
);
1203 toFixedHelpers
.multiply(1, 1);
1204 toFixedHelpers
.divide(2);
1205 m
= toFixedHelpers
.numToString();
1207 toFixedHelpers
.multiply(0, z
);
1208 toFixedHelpers
.multiply(1 << (-e
), 0);
1209 m
= toFixedHelpers
.numToString() + '0.00000000000000000000'.slice(2, 2 + f
);
1217 m
= s
+ '0.0000000000000000000'.slice(0, f
- k
+ 2) + m
;
1219 m
= s
+ m
.slice(0, k
- f
) + '.' + m
.slice(k
- f
);
1236 // http://es5.github.com/#x15.5.4.14
1238 // [bugfix, IE lt 9, firefox 4, Konqueror, Opera, obscure browsers]
1239 // Many browsers do not split properly with regular expressions or they
1240 // do not perform the split correctly under obscure conditions.
1241 // See http://blog.stevenlevithan.com/archives/cross-browser-split
1242 // I've tested in many browsers and this seems to cover the deviant ones:
1243 // 'ab'.split(/(?:ab)*/) should be ["", ""], not [""]
1244 // '.'.split(/(.?)(.?)/) should be ["", ".", "", ""], not ["", ""]
1245 // 'tesst'.split(/(s)*/) should be ["t", undefined, "e", "s", "t"], not
1246 // [undefined, "t", undefined, "e", ...]
1247 // ''.split(/.?/) should be [], not [""]
1248 // '.'.split(/()()/) should be ["."], not ["", "", "."]
1250 var string_split
= StringPrototype
.split
;
1252 'ab'.split(/(?:ab)*/).length
!== 2 ||
1253 '.'.split(/(.?)(.?)/).length
!== 4 ||
1254 'tesst'.split(/(s)*/)[1] === "t" ||
1255 'test'.split(/(?:)/, -1).length
!== 4 ||
1256 ''.split(/.?/).length
||
1257 '.'.split(/()()/).length
> 1
1260 var compliantExecNpcg
= /()??/.exec("")[1] === void 0; // NPCG: nonparticipating capturing group
1262 StringPrototype
.split = function (separator
, limit
) {
1264 if (separator
=== void 0 && limit
=== 0) {
1268 // If `separator` is not a regex, use native split
1269 if (_toString
.call(separator
) !== "[object RegExp]") {
1270 return string_split
.call(this, separator
, limit
);
1274 flags
= (separator
.ignoreCase
? "i" : "") +
1275 (separator
.multiline
? "m" : "") +
1276 (separator
.extended
? "x" : "") + // Proposed for ES6
1277 (separator
.sticky
? "y" : ""), // Firefox 3+
1279 // Make `global` and avoid `lastIndex` issues by working with a copy
1280 separator2
, match
, lastIndex
, lastLength
;
1281 separator
= new RegExp(separator
.source
, flags
+ "g");
1282 string
+= ""; // Type-convert
1283 if (!compliantExecNpcg
) {
1284 // Doesn't need flags gy, but they don't hurt
1285 separator2
= new RegExp("^" + separator
.source
+ "$(?!\\s)", flags
);
1287 /* Values for `limit`, per the spec:
1288 * If undefined: 4294967295 // Math.pow(2, 32) - 1
1289 * If 0, Infinity, or NaN: 0
1290 * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
1291 * If negative number: 4294967296 - Math.floor(Math.abs(limit))
1292 * If other: Type-convert, then use the above rules
1294 limit
= limit
=== void 0 ?
1295 -1 >>> 0 : // Math.pow(2, 32) - 1
1297 while (match
= separator
.exec(string
)) {
1298 // `separator.lastIndex` is not reliable cross-browser
1299 lastIndex
= match
.index
+ match
[0].length
;
1300 if (lastIndex
> lastLastIndex
) {
1301 output
.push(string
.slice(lastLastIndex
, match
.index
));
1302 // Fix browsers whose `exec` methods don't consistently return `undefined` for
1303 // nonparticipating capturing groups
1304 if (!compliantExecNpcg
&& match
.length
> 1) {
1305 match
[0].replace(separator2
, function () {
1306 for (var i
= 1; i
< arguments
.length
- 2; i
++) {
1307 if (arguments
[i
] === void 0) {
1313 if (match
.length
> 1 && match
.index
< string
.length
) {
1314 ArrayPrototype
.push
.apply(output
, match
.slice(1));
1316 lastLength
= match
[0].length
;
1317 lastLastIndex
= lastIndex
;
1318 if (output
.length
>= limit
) {
1322 if (separator
.lastIndex
=== match
.index
) {
1323 separator
.lastIndex
++; // Avoid an infinite loop
1326 if (lastLastIndex
=== string
.length
) {
1327 if (lastLength
|| !separator
.test("")) {
1331 output
.push(string
.slice(lastLastIndex
));
1333 return output
.length
> limit
? output
.slice(0, limit
) : output
;
1338 // If separator is undefined, then the result array contains just one String,
1339 // which is the this value (converted to a String). If limit is not undefined,
1340 // then the output array is truncated so that it contains no more than limit
1342 // "0".split(undefined, 0) -> []
1343 } else if ("0".split(void 0, 0).length
) {
1344 StringPrototype
.split
= function split(separator
, limit
) {
1345 if (separator
=== void 0 && limit
=== 0) { return []; }
1346 return string_split
.call(this, separator
, limit
);
1350 var str_replace
= StringPrototype
.replace
;
1351 var replaceReportsGroupsCorrectly
= (function () {
1353 'x'.replace(/x(.)?/g, function (match
, group
) {
1356 return groups
.length
=== 1 && typeof groups
[0] === 'undefined';
1359 if (!replaceReportsGroupsCorrectly
) {
1360 StringPrototype
.replace
= function replace(searchValue
, replaceValue
) {
1361 var isFn
= isFunction(replaceValue
);
1362 var hasCapturingGroups
= isRegex(searchValue
) && (/\)[*?]/).test(searchValue
.source
);
1363 if (!isFn
|| !hasCapturingGroups
) {
1364 return str_replace
.call(this, searchValue
, replaceValue
);
1366 var wrappedReplaceValue = function (match
) {
1367 var length
= arguments
.length
;
1368 var originalLastIndex
= searchValue
.lastIndex
;
1369 searchValue
.lastIndex
= 0;
1370 var args
= searchValue
.exec(match
);
1371 searchValue
.lastIndex
= originalLastIndex
;
1372 args
.push(arguments
[length
- 2], arguments
[length
- 1]);
1373 return replaceValue
.apply(this, args
);
1375 return str_replace
.call(this, searchValue
, wrappedReplaceValue
);
1380 // ECMA-262, 3rd B.2.3
1381 // Not an ECMAScript standard, although ECMAScript 3rd Edition has a
1382 // non-normative section suggesting uniform semantics and it should be
1383 // normalized across all browsers
1384 // [bugfix, IE lt 9] IE < 9 substr() with negative value not working in IE
1385 var string_substr
= StringPrototype
.substr
;
1386 var hasNegativeSubstrBug
= "".substr
&& "0b".substr(-1) !== "b";
1387 defineProperties(StringPrototype
, {
1388 substr
: function substr(start
, length
) {
1389 return string_substr
.call(
1391 start
< 0 ? ((start
= this.length
+ start
) < 0 ? 0 : start
) : start
,
1395 }, hasNegativeSubstrBug
);
1398 // whitespace from: http://es5.github.io/#x15.5.4.20
1399 var ws
= "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" +
1400 "\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" +
1402 var zeroWidth
= '\u200b';
1403 var wsRegexChars
= "[" + ws
+ "]";
1404 var trimBeginRegexp
= new RegExp("^" + wsRegexChars
+ wsRegexChars
+ "*");
1405 var trimEndRegexp
= new RegExp(wsRegexChars
+ wsRegexChars
+ "*$");
1406 var hasTrimWhitespaceBug
= StringPrototype
.trim
&& (ws
.trim() || !zeroWidth
.trim());
1407 defineProperties(StringPrototype
, {
1408 // http://blog.stevenlevithan.com/archives/faster-trim-javascript
1409 // http://perfectionkills.com/whitespace-deviations/
1410 trim
: function trim() {
1411 if (this === void 0 || this === null) {
1412 throw new TypeError("can't convert " + this + " to object");
1414 return String(this).replace(trimBeginRegexp
, "").replace(trimEndRegexp
, "");
1416 }, hasTrimWhitespaceBug
);
1419 if (parseInt(ws
+ '08') !== 8 || parseInt(ws
+ '0x16') !== 22) {
1420 parseInt
= (function (origParseInt
) {
1421 var hexRegex
= /^0[xX]/;
1422 return function parseIntES5(str
, radix
) {
1423 str
= String(str
).trim();
1424 if (!Number(radix
)) {
1425 radix
= hexRegex
.test(str
) ? 16 : 10;
1427 return origParseInt(str
, radix
);