[Pkg-javascript-commits] [node-es5-shim] 03/06: Imported Upstream version 4.5.8

Julien Puydt julien.puydt at laposte.net
Sat May 14 14:01:40 UTC 2016


This is an automated email from the git hooks/post-receive script.

jpuydt-guest pushed a commit to branch master
in repository node-es5-shim.

commit 2a62a63dc87a3450c85d0e50d7d747ebcb7e9f4e
Author: Julien Puydt <julien.puydt at laposte.net>
Date:   Sat May 14 14:44:56 2016 +0200

    Imported Upstream version 4.5.8
---
 .jscs.json                  |  19 +-
 .travis.yml                 |  24 ++-
 CHANGES                     |  62 ++++++
 LICENSE                     |   2 +-
 README.md                   |  14 ++
 component.json              |   2 +-
 es5-sham.js                 |   3 +-
 es5-sham.min.js             |   2 +-
 es5-shim.js                 | 316 ++++++++++++++++++++++++-----
 es5-shim.map                |   2 +-
 es5-shim.min.js             |   4 +-
 package.json                |  20 +-
 tests/.eslintrc             |   5 +
 tests/helpers/h-matchers.js |   3 +-
 tests/index.html            |   2 +-
 tests/index.min.html        |   3 +-
 tests/lib/json2.js          | 478 --------------------------------------------
 tests/native.html           |   2 +-
 tests/spec/s-array.js       |   4 +
 tests/spec/s-date.js        | 382 ++++++++++++++++++++++++++++++-----
 tests/spec/s-global.js      |  18 ++
 tests/spec/s-object.js      |   5 +-
 tests/spec/s-string.js      |   4 +
 23 files changed, 778 insertions(+), 598 deletions(-)

diff --git a/.jscs.json b/.jscs.json
index 629794b..94e1055 100644
--- a/.jscs.json
+++ b/.jscs.json
@@ -147,6 +147,23 @@
 
 	"requireEnhancedObjectLiterals": false,
 
-	"requireObjectDestructuring": false
+	"requireObjectDestructuring": false,
+
+	"requireEarlyReturn": false,
+
+	"requireCapitalizedConstructorsNew": {
+		"allExcept": ["Function", "String", "Object", "Symbol", "Number", "Date", "RegExp", "Error", "Boolean", "Array"]
+	},
+
+	"requireImportAlphabetized": false,
+
+    "requireSpaceBeforeObjectValues": true,
+    "requireSpaceBeforeDestructuredValues": true,
+
+	"disallowSpacesInsideTemplateStringPlaceholders": true,
+
+    "disallowArrayDestructuringReturn": false,
+
+    "requireNewlineBeforeSingleStatementsInIf": false
 }
 
diff --git a/.travis.yml b/.travis.yml
index 95aa579..853c56f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,18 @@
 language: node_js
 node_js:
+  - "5.10"
+  - "5.9"
+  - "5.8"
+  - "5.7"
+  - "5.6"
+  - "5.5"
+  - "5.4"
+  - "5.3"
+  - "5.2"
   - "5.1"
   - "5.0"
+  - "4.4"
+  - "4.3"
   - "4.2"
   - "4.1"
   - "4.0"
@@ -35,12 +46,23 @@ before_install:
   - 'if [ "${TRAVIS_NODE_VERSION}" != "0.9" ]; then case "$(npm --version)" in 1.*) npm install -g npm at 1.4.28 ;; 2.*) npm install -g npm at 2 ;; esac ; fi'
   - 'if [ "${TRAVIS_NODE_VERSION}" != "0.6" ] && [ "${TRAVIS_NODE_VERSION}" != "0.9" ]; then npm install -g npm; fi'
 script:
-  - 'if [ "${TRAVIS_NODE_VERSION}" != "4.2" ]; then npm run tests-only ; else npm test ; fi'
+  - 'if [ "${TRAVIS_NODE_VERSION}" != "4.4" ]; then npm run tests-only ; else npm test ; fi'
 sudo: false
 matrix:
   fast_finish: true
   allow_failures:
+    - node_js: "5.9"
+    - node_js: "5.8"
+    - node_js: "5.7"
+    - node_js: "5.6"
+    - node_js: "5.5"
+    - node_js: "5.4"
+    - node_js: "5.3"
+    - node_js: "5.2"
+    - node_js: "5.1"
     - node_js: "5.0"
+    - node_js: "4.3"
+    - node_js: "4.2"
     - node_js: "4.1"
     - node_js: "4.0"
     - node_js: "iojs-v3.2"
diff --git a/CHANGES b/CHANGES
index c96bd0d..36b87bb 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,56 @@
+4.5.8
+  - [Fix] Check if property descriptor is configurable before re-defining it (#394, #373)
+  - [Dev Deps] update `eslint`, `jscs`, `@ljharb/eslint-config`
+  - [Tests] up to `node` `v5.10`, `v4.4`
+  - [Tests] Use `concurrently` instead of `parallelshell`
+  - [Tests] use `pretest` to run the linter
+
+4.5.7
+  - [Fix] `bind` in IE 8: Update `is-callable` implementation to v1.1.3 (#390)
+
+4.5.6
+  - [Fix] `new Date(new Date())` should work in IE 8 (#389)
+  - [Tests] on `node` `v5.7`
+  - [Dev Deps] update `uglify-js`
+
+4.5.5
+  - [Fix] Adobe Photoshop’s JS engine bizarrely can have `+date !== date.getTime()` (#365)
+  - [Dev Deps] update `eslint`
+  - [Refactor] Update `is-callable` implementation to match latest
+  - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `jscs`
+
+4.5.4
+  - [Fix] careless error from 5cf99aca49e59bae03b5d542381424bb1b13ec42
+
+4.5.3
+  - [Fix] Saturday is a day in the week (#386)
+  - [Robustness] improve Function#bind (#381)
+  - [Tests] on `node` `v5.6`, `v4.3`
+  - [Tests] use json3 (#382)
+  - [Dev Deps] update `eslint`, `@ljharb/eslint-config`
+  - [Docs] add note about script order (#379)
+
+4.5.2
+  - [shim: fix] use `Array#slice`, not `String#slice`, on `String#split` output (#380)
+
+4.5.1
+  - [Fix] Make sure preexisting + broken `Array#` methods that throw don’t break the runtime (#377)
+  - [Dev Deps] update `jscs`
+
+4.5.0
+  - [New] `parseFloat('-0')` should return -0 in Opera 12 (#371)
+  - [New] Provide and replace Date UTC methods (#360)
+  - [Robustness] cache `Date` getUTC* methods so that `Date#toISOString` doesn’t observably look them up on the receiver
+  - [Robustness] use a cached and shimmed `String#trim`
+  - [Tests] up to `node` `v5.5`
+  - [Tests] add `parallelshell` and use it in a few tasks
+  - [Refactor] rename cached methods to avoid linter warnings
+  - [Dev Deps] update `eslint`, `jscs`, '@ljharb/eslint-config'
+  - [Docs] Update license year to 2016 (#374)
+
+4.4.2
+  - [shim: fix] use `Array#slice`, not `String#slice`, on `String#split` output (#380)
+
 4.4.1
   - [Fix] ensure that IE 11 in compatibility mode doesn't throw (#370)
   - [Docs] add missing shimmed things
@@ -17,6 +70,9 @@
   - [Dev Deps] update `uglify-js`, `eslint`, `jscs`, `uglify-js`, `semver`
   - [Docs] Fix broken UMD links (#344)
 
+4.3.2
+  - [shim: fix] use `Array#slice`, not `String#slice`, on `String#split` output (#380)
+
 4.3.1
   - [Fix] `String#split`: revert part of dcce96ae21185a69d2d40e67416e7496b73e8e47 which broke in older browsers (#342)
   - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `jscs`
@@ -44,10 +100,16 @@
   - [Tests] on `node` `v5.0`
   - [Tests] fix npm upgrades for older nodes
 
+4.2.1
+  - [shim: fix] use `Array#slice`, not `String#slice`, on `String#split` output (#380)
+
 4.2.0
   - [shim: new] Overwrite `String#lastIndexOf` in IE 9, 10, 11, and Edge, so it has proper unicode support.
   - [Dev Deps] update `eslint`, `jscs`
 
+4.1.16
+  - [shim: fix] use `Array#slice`, not `String#slice`, on `String#split` output (#380)
+
 4.1.15
   - [shim: fix] new Date + Date.parse: Fix a Safari 8 & 9 bug where the `ms` arg is treated as a signed instead of unsigned int (#329)
   - [shim: fix] add 'frame' to blacklisted keys (#330)
diff --git a/LICENSE b/LICENSE
index 3dbd7de..195f751 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
 The MIT License (MIT)
 
-Copyright (C) 2009-2014 Kristopher Michael Kowal and contributors
+Copyright (C) 2009-2016 Kristopher Michael Kowal and contributors
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index 12549e1..89c59bb 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,8 @@
 `es5-shim.js` and `es5-shim.min.js` monkey-patch a JavaScript context to
 contain all EcmaScript 5 methods that can be faithfully emulated with a
 legacy JavaScript engine.
+**Note:** As `es5-shim.js` is designed to patch the native Javascript
+engine, it should be the library that is loaded first.
 
 `es5-sham.js` and `es5-sham.min.js` monkey-patch other ES5 methods as
 closely as possible.  For these methods, as closely as possible to ES5
@@ -62,6 +64,7 @@ simply `npm install` and `npm test`.
 * Date.parse (for ISO parsing)
 * Date.prototype.toISOString
 * parseInt
+* parseFloat
 * Error.prototype.toString
 * Error.prototype.name
 * Error.prototype.message
@@ -165,6 +168,17 @@ simply `npm install` and `npm test`.
     provisions of this method, which you cannot possibly
     obtain in legacy engines.
 
+### Example of applying ES compatability shims in a browser project
+
+```html
+<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.7/es5-shim.min.js"></script>
+<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.7/es5-sham.min.js"></script>
+<script src="https://cdnjs.cloudflare.com/ajax/libs/json3/3.3.2/json3.min.js"></script>
+<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.34.2/es6-shim.min.js"></script>
+<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.34.2/es6-sham.min.js"></script>
+<script src="https://wzrd.in/standalone/es7-shim@latest"></script>
+<script src="other-libs.js"></script>
+```
 [npm-url]: https://npmjs.org/package/es5-shim
 [npm-version-svg]: http://versionbadg.es/es-shims/es5-shim.svg
 [travis-svg]: https://travis-ci.org/es-shims/es5-shim.svg
diff --git a/component.json b/component.json
index afc39c4..7096633 100644
--- a/component.json
+++ b/component.json
@@ -2,7 +2,7 @@
     "name": "es5-shim",
     "repo": "es-shims/es5-shim",
     "description": "ECMAScript 5 compatibility shims for legacy JavaScript engines",
-    "version": "v4.4.1",
+    "version": "v4.5.1",
     "keywords": [
         "shim",
         "es5",
diff --git a/es5-sham.js b/es5-sham.js
index bc21634..2de88d4 100644
--- a/es5-sham.js
+++ b/es5-sham.js
@@ -228,7 +228,8 @@ if (!Object.create) {
 
         xDoc = new ActiveXObject('htmlfile');
 
-        xDoc.write('<script><\/script>');
+		var script = 'script';
+        xDoc.write('<' + script + '></' + script + '>');
         xDoc.close();
 
         empty = xDoc.parentWindow.Object.prototype;
diff --git a/es5-sham.min.js b/es5-sham.min.js
index 389699d..bc8a390 100644
--- a/es5-sham.min.js
+++ b/es5-sham.min.js
@@ -1,7 +1,7 @@
 /*!
  * https://github.com/es-shims/es5-shim
  * @license es5-shim Copyright 2009-2015 by contributors, MIT License
- * see https://github.com/es-shims/es5-shim/blob/v4.4.1/LICENSE
+ * see https://github.com/es-shims/es5-shim/blob/v4.5.7/LICENSE
  */
 (function(e,t){"use strict";if(typeof define==="function"&&define.amd){define(t)}else if(typeof exports==="object"){module.exports=t()}else{e.returnExports=t()}})(this,function(){var e=Function.call;var t=Object.prototype;var r=e.bind(t.hasOwnProperty);var n=e.bind(t.propertyIsEnumerable);var o=e.bind(t.toString);var i;var c;var f;var a;var l=r(t,"__defineGetter__");if(l){i=e.bind(t.__defineGetter__);c=e.bind(t.__defineSetter__);f=e.bind(t.__lookupGetter__);a=e.bind(t.__lookupSetter__)}i [...]
 //# sourceMappingURL=es5-sham.map
diff --git a/es5-shim.js b/es5-shim.js
index 6022eee..91a7a39 100644
--- a/es5-shim.js
+++ b/es5-shim.js
@@ -45,7 +45,8 @@ var $Array = Array;
 var ArrayPrototype = $Array.prototype;
 var $Object = Object;
 var ObjectPrototype = $Object.prototype;
-var FunctionPrototype = Function.prototype;
+var $Function = Function;
+var FunctionPrototype = $Function.prototype;
 var $String = String;
 var StringPrototype = $String.prototype;
 var $Number = Number;
@@ -55,6 +56,7 @@ var array_splice = ArrayPrototype.splice;
 var array_push = ArrayPrototype.push;
 var array_unshift = ArrayPrototype.unshift;
 var array_concat = ArrayPrototype.concat;
+var array_join = ArrayPrototype.join;
 var call = FunctionPrototype.call;
 var apply = FunctionPrototype.apply;
 var max = Math.max;
@@ -63,10 +65,14 @@ var min = Math.min;
 // Having a toString local variable name breaks in Opera so use to_string.
 var to_string = ObjectPrototype.toString;
 
+/* global Symbol */
+/* eslint-disable one-var-declaration-per-line, no-redeclare, max-statements-per-line */
 var hasToStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol';
-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(val [...]
+var isCallable; /* inlined from https://npmjs.com/is-callable */ var fnToStr = Function.prototype.toString, constructorRegex = /^\s*class /, isES6ClassFn = function isES6ClassFn(value) { try { var fnStr = fnToStr.call(value); var singleStripped = fnStr.replace(/\/\/.*\n/g, ''); var multiStripped = singleStripped.replace(/\/\*[.\s\S]*\*\//g, ''); var spaceStripped = multiStripped.replace(/\n/mg, ' ').replace(/ {2}/g, ' '); return constructorRegex.test(spaceStripped); } catch (e) { return  [...]
+
 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; };
 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; };
+/* eslint-enable one-var-declaration-per-line, no-redeclare, max-statements-per-line */
 
 /* inlined from http://npmjs.com/define-properties */
 var supportsDescriptors = $Object.defineProperty && (function () {
@@ -226,7 +232,8 @@ defineProperties(FunctionPrototype, {
                 // 5. Return the result of calling the [[Construct]] internal
                 //   method of target providing args as the arguments.
 
-                var result = target.apply(
+                var result = apply.call(
+                    target,
                     this,
                     array_concat.call(args, array_slice.call(arguments))
                 );
@@ -255,7 +262,8 @@ defineProperties(FunctionPrototype, {
                 //   providing args as the arguments.
 
                 // equiv: target.call(this, ...boundArgs, ...args)
-                return target.apply(
+                return apply.call(
+                    target,
                     that,
                     array_concat.call(args, array_slice.call(arguments))
                 );
@@ -285,7 +293,7 @@ defineProperties(FunctionPrototype, {
         // for ex.) all use of eval or Function costructor throws an exception.
         // However in all of these environments Function.prototype.bind exists
         // and so this code will never be executed.
-        bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this, arguments); }')(binder);
+        bound = $Function('binder', 'return function (' + array_join.call(boundArgs, ',') + '){ return binder.apply(this, arguments); }')(binder);
 
         if (target.prototype) {
             Empty.prototype = target.prototype;
@@ -328,7 +336,7 @@ var arraySliceApply = apply.bind(array_slice);
 var strSlice = call.bind(StringPrototype.slice);
 var strSplit = call.bind(StringPrototype.split);
 var strIndexOf = call.bind(StringPrototype.indexOf);
-var push = call.bind(array_push);
+var pushCall = call.bind(array_push);
 var isEnum = call.bind(ObjectPrototype.propertyIsEnumerable);
 var arraySort = call.bind(ArrayPrototype.sort);
 
@@ -384,18 +392,25 @@ var properlyBoxesContext = function properlyBoxed(method) {
     // Check node 0.6.21 bug where third parameter is not boxed
     var properlyBoxesNonStrict = true;
     var properlyBoxesStrict = true;
+    var threwException = false;
     if (method) {
-        method.call('foo', function (_, __, context) {
-            if (typeof context !== 'object') { properlyBoxesNonStrict = false; }
-        });
+        try {
+            method.call('foo', function (_, __, context) {
+                if (typeof context !== 'object') {
+                    properlyBoxesNonStrict = false;
+                }
+            });
 
-        method.call([1], function () {
-            'use strict';
+            method.call([1], function () {
+                'use strict';
 
-            properlyBoxesStrict = typeof this === 'string';
-        }, 'x');
+                properlyBoxesStrict = typeof this === 'string';
+            }, 'x');
+        } catch (e) {
+            threwException = true;
+        }
     }
-    return !!method && properlyBoxesNonStrict && properlyBoxesStrict;
+    return !!method && !threwException && properlyBoxesNonStrict && properlyBoxesStrict;
 };
 
 defineProperties(ArrayPrototype, {
@@ -484,7 +499,7 @@ defineProperties(ArrayPrototype, {
             if (i in self) {
                 value = self[i];
                 if (typeof T === 'undefined' ? callbackfn(value, i, object) : callbackfn.call(T, value, i, object)) {
-                    push(result, value);
+                    pushCall(result, value);
                 }
             }
         }
@@ -551,7 +566,9 @@ defineProperties(ArrayPrototype, {
 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce
 var reduceCoercesToObject = false;
 if (ArrayPrototype.reduce) {
-    reduceCoercesToObject = typeof ArrayPrototype.reduce.call('es5', function (_, __, ___, list) { return list; }) === 'object';
+    reduceCoercesToObject = typeof ArrayPrototype.reduce.call('es5', function (_, __, ___, list) {
+        return list;
+    }) === 'object';
 }
 defineProperties(ArrayPrototype, {
     reduce: function reduce(callbackfn/*, initialValue*/) {
@@ -602,7 +619,9 @@ defineProperties(ArrayPrototype, {
 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight
 var reduceRightCoercesToObject = false;
 if (ArrayPrototype.reduceRight) {
-    reduceRightCoercesToObject = typeof ArrayPrototype.reduceRight.call('es5', function (_, __, ___, list) { return list; }) === 'object';
+    reduceRightCoercesToObject = typeof ArrayPrototype.reduceRight.call('es5', function (_, __, ___, list) {
+        return list;
+    }) === 'object';
 }
 defineProperties(ArrayPrototype, {
     reduceRight: function reduceRight(callbackfn/*, initial*/) {
@@ -739,7 +758,7 @@ defineProperties(ArrayPrototype, {
         if (arguments.length > 0 && typeof deleteCount !== 'number') {
             args = arraySlice(arguments);
             if (args.length < 2) {
-                push(args, this.length - start);
+                pushCall(args, this.length - start);
             } else {
                 args[1] = ES.ToInteger(deleteCount);
             }
@@ -791,7 +810,8 @@ defineProperties(ArrayPrototype, {
         var to;
         if (itemCount < actualDeleteCount) {
             k = actualStart;
-            while (k < (len - actualDeleteCount)) {
+            var maxK = len - actualDeleteCount;
+            while (k < maxK) {
                 from = $String(k + actualDeleteCount);
                 to = $String(k + itemCount);
                 if (owns(O, from)) {
@@ -802,7 +822,8 @@ defineProperties(ArrayPrototype, {
                 k += 1;
             }
             k = len;
-            while (k > (len - actualDeleteCount + itemCount)) {
+            var minK = len - actualDeleteCount + itemCount;
+            while (k > minK) {
                 delete O[k - 1];
                 k -= 1;
             }
@@ -1027,14 +1048,14 @@ defineProperties($Object, {
         var skipProto = hasProtoEnumBug && isFn;
         if ((isStr && hasStringEnumBug) || isArgs) {
             for (var i = 0; i < object.length; ++i) {
-                push(theKeys, $String(i));
+                pushCall(theKeys, $String(i));
             }
         }
 
         if (!isArgs) {
             for (var name in object) {
                 if (!(skipProto && name === 'prototype') && owns(object, name)) {
-                    push(theKeys, $String(name));
+                    pushCall(theKeys, $String(name));
                 }
             }
         }
@@ -1044,7 +1065,7 @@ defineProperties($Object, {
             for (var j = 0; j < dontEnumsLength; j++) {
                 var dontEnum = dontEnums[j];
                 if (!(skipConstructor && dontEnum === 'constructor') && owns(object, dontEnum)) {
-                    push(theKeys, dontEnum);
+                    pushCall(theKeys, dontEnum);
                 }
             }
         }
@@ -1076,6 +1097,190 @@ defineProperties($Object, {
 // ====
 //
 
+var hasNegativeMonthYearBug = new Date(-3509827329600292).getUTCMonth() !== 0;
+var aNegativeTestDate = new Date(-1509842289600292);
+var aPositiveTestDate = new Date(1449662400000);
+var hasToUTCStringFormatBug = aNegativeTestDate.toUTCString() !== 'Mon, 01 Jan -45875 11:59:59 GMT';
+var hasToDateStringFormatBug;
+var hasToStringFormatBug;
+var timeZoneOffset = aNegativeTestDate.getTimezoneOffset();
+if (timeZoneOffset < -720) {
+    hasToDateStringFormatBug = aNegativeTestDate.toDateString() !== 'Tue Jan 02 -45875';
+    hasToStringFormatBug = !(/^Thu Dec 10 2015 \d\d:\d\d:\d\d GMT[-\+]\d\d\d\d(?: |$)/).test(aPositiveTestDate.toString());
+} else {
+    hasToDateStringFormatBug = aNegativeTestDate.toDateString() !== 'Mon Jan 01 -45875';
+    hasToStringFormatBug = !(/^Wed Dec 09 2015 \d\d:\d\d:\d\d GMT[-\+]\d\d\d\d(?: |$)/).test(aPositiveTestDate.toString());
+}
+
+var originalGetFullYear = call.bind(Date.prototype.getFullYear);
+var originalGetMonth = call.bind(Date.prototype.getMonth);
+var originalGetDate = call.bind(Date.prototype.getDate);
+var originalGetUTCFullYear = call.bind(Date.prototype.getUTCFullYear);
+var originalGetUTCMonth = call.bind(Date.prototype.getUTCMonth);
+var originalGetUTCDate = call.bind(Date.prototype.getUTCDate);
+var originalGetUTCDay = call.bind(Date.prototype.getUTCDay);
+var originalGetUTCHours = call.bind(Date.prototype.getUTCHours);
+var originalGetUTCMinutes = call.bind(Date.prototype.getUTCMinutes);
+var originalGetUTCSeconds = call.bind(Date.prototype.getUTCSeconds);
+var originalGetUTCMilliseconds = call.bind(Date.prototype.getUTCMilliseconds);
+var dayName = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
+var monthName = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+var daysInMonth = function daysInMonth(month, year) {
+    return originalGetDate(new Date(year, month, 0));
+};
+
+defineProperties(Date.prototype, {
+    getFullYear: function getFullYear() {
+        if (!this || !(this instanceof Date)) {
+            throw new TypeError('this is not a Date object.');
+        }
+        var year = originalGetFullYear(this);
+        if (year < 0 && originalGetMonth(this) > 11) {
+            return year + 1;
+        }
+        return year;
+    },
+    getMonth: function getMonth() {
+        if (!this || !(this instanceof Date)) {
+            throw new TypeError('this is not a Date object.');
+        }
+        var year = originalGetFullYear(this);
+        var month = originalGetMonth(this);
+        if (year < 0 && month > 11) {
+            return 0;
+        }
+        return month;
+    },
+    getDate: function getDate() {
+        if (!this || !(this instanceof Date)) {
+            throw new TypeError('this is not a Date object.');
+        }
+        var year = originalGetFullYear(this);
+        var month = originalGetMonth(this);
+        var date = originalGetDate(this);
+        if (year < 0 && month > 11) {
+            if (month === 12) {
+                return date;
+            }
+            var days = daysInMonth(0, year + 1);
+            return (days - date) + 1;
+        }
+        return date;
+    },
+    getUTCFullYear: function getUTCFullYear() {
+        if (!this || !(this instanceof Date)) {
+            throw new TypeError('this is not a Date object.');
+        }
+        var year = originalGetUTCFullYear(this);
+        if (year < 0 && originalGetUTCMonth(this) > 11) {
+            return year + 1;
+        }
+        return year;
+    },
+    getUTCMonth: function getUTCMonth() {
+        if (!this || !(this instanceof Date)) {
+            throw new TypeError('this is not a Date object.');
+        }
+        var year = originalGetUTCFullYear(this);
+        var month = originalGetUTCMonth(this);
+        if (year < 0 && month > 11) {
+            return 0;
+        }
+        return month;
+    },
+    getUTCDate: function getUTCDate() {
+        if (!this || !(this instanceof Date)) {
+            throw new TypeError('this is not a Date object.');
+        }
+        var year = originalGetUTCFullYear(this);
+        var month = originalGetUTCMonth(this);
+        var date = originalGetUTCDate(this);
+        if (year < 0 && month > 11) {
+            if (month === 12) {
+                return date;
+            }
+            var days = daysInMonth(0, year + 1);
+            return (days - date) + 1;
+        }
+        return date;
+    }
+}, hasNegativeMonthYearBug);
+
+defineProperties(Date.prototype, {
+    toUTCString: function toUTCString() {
+        if (!this || !(this instanceof Date)) {
+            throw new TypeError('this is not a Date object.');
+        }
+        var day = originalGetUTCDay(this);
+        var date = originalGetUTCDate(this);
+        var month = originalGetUTCMonth(this);
+        var year = originalGetUTCFullYear(this);
+        var hour = originalGetUTCHours(this);
+        var minute = originalGetUTCMinutes(this);
+        var second = originalGetUTCSeconds(this);
+        return dayName[day] + ', ' +
+            (date < 10 ? '0' + date : date) + ' ' +
+            monthName[month] + ' ' +
+            year + ' ' +
+            (hour < 10 ? '0' + hour : hour) + ':' +
+            (minute < 10 ? '0' + minute : minute) + ':' +
+            (second < 10 ? '0' + second : second) + ' GMT';
+    }
+}, hasNegativeMonthYearBug || hasToUTCStringFormatBug);
+
+// Opera 12 has `,`
+defineProperties(Date.prototype, {
+    toDateString: function toDateString() {
+        if (!this || !(this instanceof Date)) {
+            throw new TypeError('this is not a Date object.');
+        }
+        var day = this.getDay();
+        var date = this.getDate();
+        var month = this.getMonth();
+        var year = this.getFullYear();
+        return dayName[day] + ' ' +
+            monthName[month] + ' ' +
+            (date < 10 ? '0' + date : date) + ' ' +
+            year;
+    }
+}, hasNegativeMonthYearBug || hasToDateStringFormatBug);
+
+// can't use defineProperties here because of toString enumeration issue in IE <= 8
+if (hasNegativeMonthYearBug || hasToStringFormatBug) {
+    Date.prototype.toString = function toString() {
+        if (!this || !(this instanceof Date)) {
+            throw new TypeError('this is not a Date object.');
+        }
+        var day = this.getDay();
+        var date = this.getDate();
+        var month = this.getMonth();
+        var year = this.getFullYear();
+        var hour = this.getHours();
+        var minute = this.getMinutes();
+        var second = this.getSeconds();
+        var timezoneOffset = this.getTimezoneOffset();
+        var hoursOffset = Math.floor(Math.abs(timezoneOffset) / 60);
+        var minutesOffset = Math.floor(Math.abs(timezoneOffset) % 60);
+        return dayName[day] + ' ' +
+            monthName[month] + ' ' +
+            (date < 10 ? '0' + date : date) + ' ' +
+            year + ' ' +
+            (hour < 10 ? '0' + hour : hour) + ':' +
+            (minute < 10 ? '0' + minute : minute) + ':' +
+            (second < 10 ? '0' + second : second) + ' GMT' +
+            (timezoneOffset > 0 ? '-' : '+') +
+            (hoursOffset < 10 ? '0' + hoursOffset : hoursOffset) +
+            (minutesOffset < 10 ? '0' + minutesOffset : minutesOffset);
+    };
+    if (supportsDescriptors) {
+        $Object.defineProperty(Date.prototype, 'toString', {
+            configurable: true,
+            enumerable: false,
+            writable: true
+        });
+    }
+}
+
 // ES5 15.9.5.43
 // http://es5.github.com/#x15.9.5.43
 // This function returns a String value represent the instance in time
@@ -1088,41 +1293,38 @@ var negativeYearString = '-000001';
 var hasNegativeDateBug = Date.prototype.toISOString && new Date(negativeDate).toISOString().indexOf(negativeYearString) === -1;
 var hasSafari51DateBug = Date.prototype.toISOString && new Date(-1).toISOString() !== '1969-12-31T23:59:59.999Z';
 
+var getTime = call.bind(Date.prototype.getTime);
+
 defineProperties(Date.prototype, {
     toISOString: function toISOString() {
-        var result, length, value, year, month;
-        if (!isFinite(this)) {
+        if (!isFinite(this) || !isFinite(getTime(this))) {
+            // Adope Photoshop requires the second check.
             throw new RangeError('Date.prototype.toISOString called on non-finite value.');
         }
 
-        year = this.getUTCFullYear();
+        var year = originalGetUTCFullYear(this);
 
-        month = this.getUTCMonth();
+        var month = originalGetUTCMonth(this);
         // see https://github.com/es-shims/es5-shim/issues/111
         year += Math.floor(month / 12);
         month = (month % 12 + 12) % 12;
 
         // the date time string format is specified in 15.9.1.15.
-        result = [month + 1, this.getUTCDate(), this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds()];
+        var result = [month + 1, originalGetUTCDate(this), originalGetUTCHours(this), originalGetUTCMinutes(this), originalGetUTCSeconds(this)];
         year = (
             (year < 0 ? '-' : (year > 9999 ? '+' : '')) +
             strSlice('00000' + Math.abs(year), (0 <= year && year <= 9999) ? -4 : -6)
         );
 
-        length = result.length;
-        while (length--) {
-            value = result[length];
-            // pad months, days, hours, minutes, and seconds to have two
-            // digits.
-            if (value < 10) {
-                result[length] = '0' + value;
-            }
+        for (var i = 0; i < result.length; ++i) {
+          // pad months, days, hours, minutes, and seconds to have two digits.
+          result[i] = strSlice('00' + result[i], -2);
         }
         // pad milliseconds to have three digits.
         return (
             year + '-' + arraySlice(result, 0, 2).join('-') +
             'T' + arraySlice(result, 2).join(':') + '.' +
-            strSlice('000' + this.getUTCMilliseconds(), -3) + 'Z'
+            strSlice('000' + originalGetUTCMilliseconds(this), -3) + 'Z'
         );
     }
 }, hasNegativeDateBug || hasSafari51DateBug);
@@ -1193,7 +1395,9 @@ if (doesNotParseY2KNewYear || acceptsInvalidDates || !supportsExtendedYears) {
     /* eslint-disable no-undef */
     var maxSafeUnsigned32Bit = Math.pow(2, 31) - 1;
     var hasSafariSignedIntBug = isActualNaN(new Date(1970, 0, 1, 0, 0, 0, maxSafeUnsigned32Bit + 1).getTime());
+    /* eslint-disable no-implicit-globals */
     Date = (function (NativeDate) {
+    /* eslint-enable no-implicit-globals */
     /* eslint-enable no-undef */
         // Date.length === 7
         var DateShim = function Date(Y, M, D, h, m, s, ms) {
@@ -1220,7 +1424,7 @@ if (doesNotParseY2KNewYear || acceptsInvalidDates || !supportsExtendedYears) {
                     length >= 4 ? new NativeDate(Y, M, D, h) :
                     length >= 3 ? new NativeDate(Y, M, D) :
                     length >= 2 ? new NativeDate(Y, M) :
-                    length >= 1 ? new NativeDate(Y) :
+                    length >= 1 ? new NativeDate(Y instanceof NativeDate ? +Y : Y) :
                                   new NativeDate();
             } else {
                 date = NativeDate.apply(this, arguments);
@@ -1392,7 +1596,8 @@ var toFixedHelpers = {
       }
   },
   divide: function divide(n) {
-      var i = toFixedHelpers.size, c = 0;
+      var i = toFixedHelpers.size;
+      var c = 0;
       while (--i >= 0) {
           c += toFixedHelpers.data[i];
           toFixedHelpers.data[i] = Math.floor(c / n);
@@ -1600,7 +1805,7 @@ if (
                 // `separatorCopy.lastIndex` is not reliable cross-browser
                 lastIndex = match.index + match[0].length;
                 if (lastIndex > lastLastIndex) {
-                    push(output, strSlice(string, lastLastIndex, match.index));
+                    pushCall(output, strSlice(string, lastLastIndex, match.index));
                     // Fix browsers whose `exec` methods don't consistently return `undefined` for
                     // nonparticipating capturing groups
                     if (!compliantExecNpcg && match.length > 1) {
@@ -1630,12 +1835,12 @@ if (
             }
             if (lastLastIndex === string.length) {
                 if (lastLength || !separatorCopy.test('')) {
-                    push(output, '');
+                    pushCall(output, '');
                 }
             } else {
-                push(output, strSlice(string, lastLastIndex));
+                pushCall(output, strSlice(string, lastLastIndex));
             }
-            return output.length > splitLimit ? strSlice(output, 0, splitLimit) : output;
+            return output.length > splitLimit ? arraySlice(output, 0, splitLimit) : output;
         };
     }());
 
@@ -1656,7 +1861,7 @@ var str_replace = StringPrototype.replace;
 var replaceReportsGroupsCorrectly = (function () {
     var groups = [];
     'x'.replace(/x(.)?/g, function (match, group) {
-        push(groups, group);
+        pushCall(groups, group);
     });
     return groups.length === 1 && typeof groups[0] === 'undefined';
 }());
@@ -1674,7 +1879,7 @@ if (!replaceReportsGroupsCorrectly) {
                 searchValue.lastIndex = 0;
                 var args = searchValue.exec(match) || [];
                 searchValue.lastIndex = originalLastIndex;
-                push(args, arguments[length - 2], arguments[length - 1]);
+                pushCall(args, arguments[length - 2], arguments[length - 1]);
                 return replaceValue.apply(this, args);
             };
             return str_replace.call(this, searchValue, wrappedReplaceValue);
@@ -1719,6 +1924,7 @@ defineProperties(StringPrototype, {
         return $String(this).replace(trimBeginRegexp, '').replace(trimEndRegexp, '');
     }
 }, hasTrimWhitespaceBug);
+var trim = call.bind(String.prototype.trim);
 
 var hasLastIndexBug = StringPrototype.lastIndexOf && 'abcあい'.lastIndexOf('あい', 2) !== -1;
 defineProperties(StringPrototype, {
@@ -1759,13 +1965,25 @@ if (parseInt(ws + '08') !== 8 || parseInt(ws + '0x16') !== 22) {
     parseInt = (function (origParseInt) {
         var hexRegex = /^[\-+]?0[xX]/;
         return function parseInt(str, radix) {
-            var string = $String(str).trim();
+            var string = trim(str);
             var defaultedRadix = $Number(radix) || (hexRegex.test(string) ? 16 : 10);
             return origParseInt(string, defaultedRadix);
         };
     }(parseInt));
 }
 
+// https://es5.github.io/#x15.1.2.3
+if (1 / parseFloat('-0') !== -Infinity) {
+    /* global parseFloat: true */
+    parseFloat = (function (origParseFloat) {
+        return function parseFloat(string) {
+            var inputString = trim(string);
+            var result = origParseFloat(inputString);
+            return result === 0 && strSlice(inputString, 0, 1) === '-' ? -0 : result;
+        };
+    }(parseFloat));
+}
+
 if (String(new RangeError('test')) !== 'RangeError: test') {
     var errorToStringShim = function toString() {
         if (typeof this === 'undefined' || this === null) {
@@ -1799,8 +2017,10 @@ if (supportsDescriptors) {
     var ensureNonEnumerable = function (obj, prop) {
         if (isEnum(obj, prop)) {
             var desc = Object.getOwnPropertyDescriptor(obj, prop);
-            desc.enumerable = false;
-            Object.defineProperty(obj, prop, desc);
+            if (desc.configurable) {
+              desc.enumerable = false;
+              Object.defineProperty(obj, prop, desc);
+            }
         }
     };
     ensureNonEnumerable(Error.prototype, 'message');
diff --git a/es5-shim.map b/es5-shim.map
index a45d038..82d4855 100644
--- a/es5-shim.map
+++ b/es5-shim.map
@@ -1 +1 @@
-{"version":3,"sources":["es5-shim.js"],"names":["root","factory","define","amd","exports","module","returnExports","this","$Array","Array","ArrayPrototype","prototype","$Object","Object","ObjectPrototype","FunctionPrototype","Function","$String","String","StringPrototype","$Number","Number","NumberPrototype","array_slice","slice","array_splice","splice","array_push","push","array_unshift","unshift","array_concat","concat","call","apply","max","Math","min","to_string","toString","hasToStr [...]
\ No newline at end of file
+{"version":3,"sources":["es5-shim.js"],"names":["root","factory","define","amd","exports","module","returnExports","this","$Array","Array","ArrayPrototype","prototype","$Object","Object","ObjectPrototype","$Function","Function","FunctionPrototype","$String","String","StringPrototype","$Number","Number","NumberPrototype","array_slice","slice","array_splice","splice","array_push","push","array_unshift","unshift","array_concat","concat","array_join","join","call","apply","max","Math","min", [...]
\ No newline at end of file
diff --git a/es5-shim.min.js b/es5-shim.min.js
index 5b43dbe..e786c62 100644
--- a/es5-shim.min.js
+++ b/es5-shim.min.js
@@ -1,7 +1,7 @@
 /*!
  * https://github.com/es-shims/es5-shim
  * @license es5-shim Copyright 2009-2015 by contributors, MIT License
- * see https://github.com/es-shims/es5-shim/blob/v4.4.1/LICENSE
+ * see https://github.com/es-shims/es5-shim/blob/v4.5.7/LICENSE
  */
-(function(r,t){"use strict";if(typeof define==="function"&&define.amd){define(t)}else if(typeof exports==="object"){module.exports=t()}else{r.returnExports=t()}})(this,function(){var r=Array;var t=r.prototype;var e=Object;var n=e.prototype;var i=Function.prototype;var a=String;var o=a.prototype;var u=Number;var f=u.prototype;var l=t.slice;var s=t.splice;var c=t.push;var v=t.unshift;var p=t.concat;var h=i.call;var g=i.apply;var y=Math.max;var d=Math.min;var m=n.toString;var w=typeof Symbo [...]
+(function(t,r){"use strict";if(typeof define==="function"&&define.amd){define(r)}else if(typeof exports==="object"){module.exports=r()}else{t.returnExports=r()}})(this,function(){var t=Array;var r=t.prototype;var e=Object;var n=e.prototype;var i=Function;var a=i.prototype;var o=String;var f=o.prototype;var u=Number;var l=u.prototype;var s=r.slice;var c=r.splice;var v=r.push;var h=r.unshift;var p=r.concat;var y=r.join;var d=a.call;var g=a.apply;var w=Math.max;var b=Math.min;var T=n.toStri [...]
 //# sourceMappingURL=es5-shim.map
diff --git a/package.json b/package.json
index 611bbf0..b944e38 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "es5-shim",
-  "version": "4.4.1",
+  "version": "4.5.8",
   "description": "ECMAScript 5 compatibility shims for legacy JavaScript engines",
   "homepage": "http://github.com/es-shims/es5-shim/",
   "contributors": [
@@ -22,24 +22,26 @@
     "url": "http://github.com/es-shims/es5-shim.git"
   },
   "scripts": {
-    "minify": "npm run minify-shim && npm run minify-sham",
+    "minify": "concurrently --raw 'npm run --silent minify-shim' 'npm run --silent minify-sham'",
     "minify-shim": "uglifyjs es5-shim.js --keep-fnames --comments --source-map=es5-shim.map -m -b ascii_only=true,beautify=false > es5-shim.min.js",
     "minify-sham": "uglifyjs es5-sham.js --keep-fnames --comments --source-map=es5-sham.map -m -b ascii_only=true,beautify=false > es5-sham.min.js",
-    "test": "npm run lint && npm run tests-only",
+    "pretest": "npm run --silent lint",
+    "test": "npm run --silent tests-only",
     "tests-only": "jasmine-node --matchall ./ tests/spec/",
     "test-native": "jasmine-node --matchall tests/spec/",
-    "lint": "npm run jscs && npm run eslint",
+    "lint": "concurrently --raw 'npm run --silent jscs' 'npm run --silent eslint'",
     "eslint": "eslint tests/helpers/*.js tests/spec/*.js es5-shim.js es5-sham.js",
     "jscs": "jscs tests/helpers/*.js tests/spec/*.js es5-shim.js es5-sham.js"
   },
   "devDependencies": {
-    "eslint": "^1.10.1",
-    "@ljharb/eslint-config": "^1.6.0",
+    "eslint": "^2.7.0",
+    "@ljharb/eslint-config": "^2.2.0",
     "jasmine-node": "^1.14.5",
-    "jscs": "^2.6.0",
-    "uglify-js": "^2.6.1",
+    "jscs": "^2.11.0",
+    "uglify-js": "^2.6.2",
     "replace": "^0.3.0",
-    "semver": "^5.1.0"
+    "semver": "^5.1.0",
+    "concurrently": "^2.0.0"
   },
   "engines": {
     "node": ">=0.4.0"
diff --git a/tests/.eslintrc b/tests/.eslintrc
new file mode 100644
index 0000000..168cdf8
--- /dev/null
+++ b/tests/.eslintrc
@@ -0,0 +1,5 @@
+{
+	"rules": {
+		"max-statements-per-line": [2, { "max": 2 }]
+	}
+}
diff --git a/tests/helpers/h-matchers.js b/tests/helpers/h-matchers.js
index 9ce9869..556ae10 100644
--- a/tests/helpers/h-matchers.js
+++ b/tests/helpers/h-matchers.js
@@ -4,7 +4,8 @@ var has = Object.prototype.hasOwnProperty;
 var getKeys = function (o) {
     'use strict';
 
-    var key, a = [];
+    var key;
+    var a = [];
     for (key in o) {
         if (has.call(o, key)) {
             a.push(key);
diff --git a/tests/index.html b/tests/index.html
index f09492d..3c5c81f 100644
--- a/tests/index.html
+++ b/tests/index.html
@@ -9,7 +9,7 @@
 	<link rel="stylesheet" type="text/css" href="lib/jasmine.css">
 	<script type="text/javascript" src="lib/jasmine.js"></script>
 	<script type="text/javascript" src="lib/jasmine-html.js"></script>
-	<script type="text/javascript" src="lib/json2.js"></script>
+	<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/json3/3.3.2/json3.min.js"></script>
 
 	<!-- include helper files here... -->
 	<script src="helpers/h-matchers.js"></script>
diff --git a/tests/index.min.html b/tests/index.min.html
index 5a265ca..622a456 100644
--- a/tests/index.min.html
+++ b/tests/index.min.html
@@ -8,7 +8,8 @@
 	<link rel="stylesheet" type="text/css" href="lib/jasmine.css">
 	<script type="text/javascript" src="lib/jasmine.js"></script>
 	<script type="text/javascript" src="lib/jasmine-html.js"></script>
-	<script type="text/javascript" src="lib/json2.js"></script>
+	<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/json3/3.3.2/json3.min.js"></script>
+
 
 	<!-- include helper files here... -->
 	<script src="helpers/h-matchers.js"></script>
diff --git a/tests/lib/json2.js b/tests/lib/json2.js
deleted file mode 100644
index ac58079..0000000
--- a/tests/lib/json2.js
+++ /dev/null
@@ -1,478 +0,0 @@
-/*
-    http://www.JSON.org/json2.js
-    2009-08-17
-
-    Public Domain.
-
-    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
-
-    See http://www.JSON.org/js.html
-
-    This file creates a global JSON object containing two methods: stringify
-    and parse.
-
-        JSON.stringify(value, replacer, space)
-            value       any JavaScript value, usually an object or array.
-
-            replacer    an optional parameter that determines how object
-                        values are stringified for objects. It can be a
-                        function or an array of strings.
-
-            space       an optional parameter that specifies the indentation
-                        of nested structures. If it is omitted, the text will
-                        be packed without extra whitespace. If it is a number,
-                        it will specify the number of spaces to indent at each
-                        level. If it is a string (such as '\t' or ' '),
-                        it contains the characters used to indent at each level.
-
-            This method produces a JSON text from a JavaScript value.
-
-            When an object value is found, if the object contains a toJSON
-            method, its toJSON method will be called and the result will be
-            stringified. A toJSON method does not serialize: it returns the
-            value represented by the name/value pair that should be serialized,
-            or undefined if nothing should be serialized. The toJSON method
-            will be passed the key associated with the value, and this will be
-            bound to the value
-
-            For example, this would serialize Dates as ISO strings.
-
-                Date.prototype.toJSON = function (key) {
-                    function f(n) {
-                        // Format integers to have at least two digits.
-                        return n < 10 ? '0' + n : n;
-                    }
-
-                    return this.getUTCFullYear()   + '-' +
-                         f(this.getUTCMonth() + 1) + '-' +
-                         f(this.getUTCDate())      + 'T' +
-                         f(this.getUTCHours())     + ':' +
-                         f(this.getUTCMinutes())   + ':' +
-                         f(this.getUTCSeconds())   + 'Z';
-                };
-
-            You can provide an optional replacer method. It will be passed the
-            key and value of each member, with this bound to the containing
-            object. The value that is returned from your method will be
-            serialized. If your method returns undefined, then the member will
-            be excluded from the serialization.
-
-            If the replacer parameter is an array of strings, then it will be
-            used to select the members to be serialized. It filters the results
-            such that only members with keys listed in the replacer array are
-            stringified.
-
-            Values that do not have JSON representations, such as undefined or
-            functions, will not be serialized. Such values in objects will be
-            dropped; in arrays they will be replaced with null. You can use
-            a replacer function to replace those with JSON values.
-            JSON.stringify(undefined) returns undefined.
-
-            The optional space parameter produces a stringification of the
-            value that is filled with line breaks and indentation to make it
-            easier to read.
-
-            If the space parameter is a non-empty string, then that string will
-            be used for indentation. If the space parameter is a number, then
-            the indentation will be that many spaces.
-
-            Example:
-
-            text = JSON.stringify(['e', {pluribus: 'unum'}]);
-            // text is '["e",{"pluribus":"unum"}]'
-
-
-            text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
-            // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
-
-            text = JSON.stringify([new Date()], function (key, value) {
-                return this[key] instanceof Date ?
-                    'Date(' + this[key] + ')' : value;
-            });
-            // text is '["Date(---current time---)"]'
-
-
-        JSON.parse(text, reviver)
-            This method parses a JSON text to produce an object or array.
-            It can throw a SyntaxError exception.
-
-            The optional reviver parameter is a function that can filter and
-            transform the results. It receives each of the keys and values,
-            and its return value is used instead of the original value.
-            If it returns what it received, then the structure is not modified.
-            If it returns undefined then the member is deleted.
-
-            Example:
-
-            // Parse the text. Values that look like ISO date strings will
-            // be converted to Date objects.
-
-            myData = JSON.parse(text, function (key, value) {
-                var a;
-                if (typeof value === 'string') {
-                    a =
-/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
-                    if (a) {
-                        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
-                            +a[5], +a[6]));
-                    }
-                }
-                return value;
-            });
-
-            myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
-                var d;
-                if (typeof value === 'string' &&
-                        value.slice(0, 5) === 'Date(' &&
-                        value.slice(-1) === ')') {
-                    d = new Date(value.slice(5, -1));
-                    if (d) {
-                        return d;
-                    }
-                }
-                return value;
-            });
-
-
-    This is a reference implementation. You are free to copy, modify, or
-    redistribute.
-
-    This code should be minified before deployment.
-    See http://javascript.crockford.com/jsmin.html
-
-    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
-    NOT CONTROL.
-*/
-
-/*jslint evil: true */
-
-/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
-    call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
-    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
-    lastIndex, length, parse, prototype, push, replace, slice, stringify,
-    test, toJSON, toString, valueOf
-*/
-
-"use strict";
-
-// Create a JSON object only if one does not already exist. We create the
-// methods in a closure to avoid creating global variables.
-
-if (!this.JSON) {
-    this.JSON = {};
-}
-
-(function () {
-
-    function f(n) {
-        // Format integers to have at least two digits.
-        return n < 10 ? '0' + n : n;
-    }
-
-    if (typeof Date.prototype.toJSON !== 'function') {
-
-        Date.prototype.toJSON = function (key) {
-
-            return isFinite(this.valueOf()) ?
-                   this.getUTCFullYear()   + '-' +
-                 f(this.getUTCMonth() + 1) + '-' +
-                 f(this.getUTCDate())      + 'T' +
-                 f(this.getUTCHours())     + ':' +
-                 f(this.getUTCMinutes())   + ':' +
-                 f(this.getUTCSeconds())   + 'Z' : null;
-        };
-
-        String.prototype.toJSON =
-        Number.prototype.toJSON =
-        Boolean.prototype.toJSON = function (key) {
-            return this.valueOf();
-        };
-    }
-
-    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
-        escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
-        gap,
-        indent,
-        meta = {    // table of character substitutions
-            '\b': '\\b',
-            '\t': '\\t',
-            '\n': '\\n',
-            '\f': '\\f',
-            '\r': '\\r',
-            '"' : '\\"',
-            '\\': '\\\\'
-        },
-        rep;
-
-
-    function quote(string) {
-
-// If the string contains no control characters, no quote characters, and no
-// backslash characters, then we can safely slap some quotes around it.
-// Otherwise we must also replace the offending characters with safe escape
-// sequences.
-
-        escapable.lastIndex = 0;
-        return escapable.test(string) ?
-            '"' + string.replace(escapable, function (a) {
-                var c = meta[a];
-                return typeof c === 'string' ? c :
-                    '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
-            }) + '"' :
-            '"' + string + '"';
-    }
-
-
-    function str(key, holder) {
-// Produce a string from holder[key].
-
-        var i,          // The loop counter.
-            k,          // The member key.
-            v,          // The member value.
-            length,
-            mind = gap,
-            partial,
-            value = holder[key];
-
-// If the value has a toJSON method, call it to obtain a replacement value.
-
-        if (value && typeof value === 'object' &&
-                typeof value.toJSON === 'function') {
-            value = value.toJSON(key);
-        }
-
-// If we were called with a replacer function, then call the replacer to
-// obtain a replacement value.
-
-        if (typeof rep === 'function') {
-            value = rep.call(holder, key, value);
-        }
-
-// What happens next depends on the value's type.
-
-        switch (typeof value) {
-        case 'string':
-            return quote(value);
-
-        case 'number':
-
-// JSON numbers must be finite. Encode non-finite numbers as null.
-
-            return isFinite(value) ? String(value) : 'null';
-
-        case 'boolean':
-        case 'null':
-
-// If the value is a boolean or null, convert it to a string. Note:
-// typeof null does not produce 'null'. The case is included here in
-// the remote chance that this gets fixed someday.
-
-            return String(value);
-
-// If the type is 'object', we might be dealing with an object or an array or
-// null.
-
-        case 'object':
-
-// Due to a specification blunder in ECMAScript, typeof null is 'object',
-// so watch out for that case.
-
-            if (!value) {
-                return 'null';
-            }
-
-// Make an array to hold the partial results of stringifying this object value.
-
-            gap += indent;
-            partial = [];
-
-// Is the value an array?
-
-            if (Object.prototype.toString.apply(value) === '[object Array]') {
-
-// The value is an array. Stringify every element. Use null as a placeholder
-// for non-JSON values.
-
-                length = value.length;
-                for (i = 0; i < length; i += 1) {
-                    partial[i] = str(i, value) || 'null';
-                }
-
-// Join all of the elements together, separated with commas, and wrap them in
-// brackets.
-
-                v = partial.length === 0 ? '[]' :
-                    gap ? '[\n' + gap +
-                            partial.join(',\n' + gap) + '\n' +
-                                mind + ']' :
-                          '[' + partial.join(',') + ']';
-                gap = mind;
-                return v;
-            }
-
-// If the replacer is an array, use it to select the members to be stringified.
-
-            if (rep && typeof rep === 'object') {
-                length = rep.length;
-                for (i = 0; i < length; i += 1) {
-                    k = rep[i];
-                    if (typeof k === 'string') {
-                        v = str(k, value);
-                        if (v) {
-                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
-                        }
-                    }
-                }
-            } else {
-
-// Otherwise, iterate through all of the keys in the object.
-
-                for (k in value) {
-                    if (Object.hasOwnProperty.call(value, k)) {
-                        v = str(k, value);
-                        if (v) {
-                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
-                        }
-                    }
-                }
-            }
-
-// Join all of the member texts together, separated with commas,
-// and wrap them in braces.
-
-            v = partial.length === 0 ? '{}' :
-                gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
-                        mind + '}' : '{' + partial.join(',') + '}';
-            gap = mind;
-            return v;
-        }
-    }
-
-// If the JSON object does not yet have a stringify method, give it one.
-
-    if (typeof JSON.stringify !== 'function') {
-        JSON.stringify = function (value, replacer, space) {
-// The stringify method takes a value and an optional replacer, and an optional
-// space parameter, and returns a JSON text. The replacer can be a function
-// that can replace values, or an array of strings that will select the keys.
-// A default replacer method can be provided. Use of the space parameter can
-// produce text that is more easily readable.
-
-            var i;
-            gap = '';
-            indent = '';
-
-// If the space parameter is a number, make an indent string containing that
-// many spaces.
-
-            if (typeof space === 'number') {
-                for (i = 0; i < space; i += 1) {
-                    indent += ' ';
-                }
-
-// If the space parameter is a string, it will be used as the indent string.
-
-            } else if (typeof space === 'string') {
-                indent = space;
-            }
-
-// If there is a replacer, it must be a function or an array.
-// Otherwise, throw an error.
-
-            rep = replacer;
-            if (replacer && typeof replacer !== 'function' &&
-                    (typeof replacer !== 'object' ||
-                     typeof replacer.length !== 'number')) {
-                throw new Error('JSON.stringify');
-            }
-
-// Make a fake root object containing our value under the key of ''.
-// Return the result of stringifying the value.
-
-            return str('', {'': value});
-        };
-    }
-
-
-// If the JSON object does not yet have a parse method, give it one.
-
-    if (typeof JSON.parse !== 'function') {
-        JSON.parse = function (text, reviver) {
-
-// The parse method takes a text and an optional reviver function, and returns
-// a JavaScript value if the text is a valid JSON text.
-
-            var j;
-
-            function walk(holder, key) {
-
-// The walk method is used to recursively walk the resulting structure so
-// that modifications can be made.
-
-                var k, v, value = holder[key];
-                if (value && typeof value === 'object') {
-                    for (k in value) {
-                        if (Object.hasOwnProperty.call(value, k)) {
-                            v = walk(value, k);
-                            if (v !== undefined) {
-                                value[k] = v;
-                            } else {
-                                delete value[k];
-                            }
-                        }
-                    }
-                }
-                return reviver.call(holder, key, value);
-            }
-
-
-// Parsing happens in four stages. In the first stage, we replace certain
-// Unicode characters with escape sequences. JavaScript handles many characters
-// incorrectly, either silently deleting them, or treating them as line endings.
-
-            cx.lastIndex = 0;
-            if (cx.test(text)) {
-                text = text.replace(cx, function (a) {
-                    return '\\u' +
-                        ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
-                });
-            }
-
-// In the second stage, we run the text against regular expressions that look
-// for non-JSON patterns. We are especially concerned with '()' and 'new'
-// because they can cause invocation, and '=' because it can cause mutation.
-// But just to be safe, we want to reject all unexpected forms.
-
-// We split the second stage into 4 regexp operations in order to work around
-// crippling inefficiencies in IE's and Safari's regexp engines. First we
-// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
-// replace all simple value tokens with ']' characters. Third, we delete all
-// open brackets that follow a colon or comma or that begin the text. Finally,
-// we look to see that the remaining characters are only whitespace or ']' or
-// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
-
-            if (/^[\],:{}\s]*$/.
-test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
-replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
-replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
-
-// In the third stage we use the eval function to compile the text into a
-// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
-// in JavaScript: it can begin a block or an object literal. We wrap the text
-// in parens to eliminate the ambiguity.
-
-                j = eval('(' + text + ')');
-
-// In the optional fourth stage, we recursively walk the new structure, passing
-// each name/value pair to a reviver function for possible transformation.
-
-                return typeof reviver === 'function' ?
-                    walk({'': j}, '') : j;
-            }
-
-// If the text is not JSON parseable, then a SyntaxError is thrown.
-
-            throw new SyntaxError('JSON.parse');
-        };
-    }
-}());
diff --git a/tests/native.html b/tests/native.html
index 37811fa..c6d2324 100644
--- a/tests/native.html
+++ b/tests/native.html
@@ -9,7 +9,7 @@
 	<link rel="stylesheet" type="text/css" href="lib/jasmine.css">
 	<script type="text/javascript" src="lib/jasmine.js"></script>
 	<script type="text/javascript" src="lib/jasmine-html.js"></script>
-	<script type="text/javascript" src="lib/json2.js"></script>
+	<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/json3/3.3.2/json3.min.js"></script>
 
 	<!-- include helper files here... -->
 	<script src="helpers/h-matchers.js"></script>
diff --git a/tests/spec/s-array.js b/tests/spec/s-array.js
index 734f7aa..f28891c 100644
--- a/tests/spec/s-array.js
+++ b/tests/spec/s-array.js
@@ -163,12 +163,14 @@ describe('Array', function () {
         });
 
         it('should set the right context when given none', function () {
+            /* eslint-disable array-callback-return */
             var context;
             [1].some(function () { context = this; });
             expect(context).toBe(function () { return this; }.call());
         });
 
         it('should return false if it runs to the end', function () {
+            /* eslint-disable array-callback-return */
             actual = testSubject.some(function () {});
             expect(actual).toBeFalsy();
         });
@@ -261,6 +263,7 @@ describe('Array', function () {
         });
 
         it('should set the right context when given none', function () {
+            /* eslint-disable array-callback-return */
             var context;
             [1].every(function () { context = this; });
             expect(context).toBe(function () { return this; }.call());
@@ -645,6 +648,7 @@ describe('Array', function () {
             });
 
             it('should set the right context when given none', function () {
+                /* eslint-disable array-callback-return */
                 var context;
                 [1].filter(function () { context = this; });
                 expect(context).toBe(function () { return this; }.call());
diff --git a/tests/spec/s-date.js b/tests/spec/s-date.js
index c43d64b..1684926 100644
--- a/tests/spec/s-date.js
+++ b/tests/spec/s-date.js
@@ -6,8 +6,13 @@ describe('Date', function () {
     var supportsDescriptors = Object.defineProperty && (function () {
         try {
             var obj = {};
-            Object.defineProperty(obj, 'x', { enumerable: false, value: obj });
-            for (var _ in obj) { return false; }
+            Object.defineProperty(obj, 'x', {
+                enumerable: false,
+                value: obj
+            });
+            for (var _ in obj) {
+                return false;
+            }
             return obj.x === obj;
         } catch (e) { /* this is ES3 */
             return false;
@@ -16,6 +21,94 @@ describe('Date', function () {
     var ifSupportsDescriptorsIt = supportsDescriptors ? it : xit;
     var has = Object.prototype.hasOwnProperty;
 
+    var negativeDate;
+    beforeEach(function () {
+        var negativeCanned = [
+            {
+                getTime: -3509827329600292,
+                getUTCDay: 4,
+                getDay: 4,
+                dim: 31
+            },
+            {
+                getTime: -3509824651200292,
+                getUTCDay: 0,
+                getDay: 0,
+                dim: 29
+            },
+            {
+                getTime: -3509822145600292,
+                getUTCDay: 1,
+                getDay: 1,
+                dim: 31
+            },
+            {
+                getTime: -3509819467200292,
+                getUTCDay: 4,
+                getDay: 4,
+                dim: 30
+            },
+            {
+                getTime: -3509816875200292,
+                getUTCDay: 6,
+                getDay: 6,
+                dim: 31
+            },
+            {
+                getTime: -3509814196800292,
+                getUTCDay: 2,
+                getDay: 2,
+                dim: 30
+            },
+            {
+                getTime: -3509811604800292,
+                getUTCDay: 4,
+                getDay: 4,
+                dim: 31
+            },
+            {
+                getTime: -3509808926400292,
+                getUTCDay: 0,
+                getDay: 0,
+                dim: 31
+            },
+            {
+                getTime: -3509806248000292,
+                getUTCDay: 3,
+                getDay: 3,
+                dim: 30
+            },
+            {
+                getTime: -3509803656000292,
+                getUTCDay: 5,
+                getDay: 5,
+                dim: 31
+            },
+            {
+                getTime: -3509800977600292,
+                getUTCDay: 1,
+                getDay: 1,
+                dim: 30
+            },
+            {
+                getTime: -3509798385600292,
+                getUTCDay: 3,
+                getDay: 3,
+                dim: 31
+            }
+        ];
+        negativeDate = negativeCanned.map(function (item) {
+            var dateFirst = new Date(item.getTime);
+            var dateLast = new Date(item.getTime + ((item.dim - 1) * 86400000));
+            return {
+                dates: [dateFirst, dateLast],
+                days: [1, item.dim],
+                getUTCDay: [item.getUTCDay, (item.getUTCDay + item.dim - 1) % 7],
+                getDay: [item.getDay, (item.getDay + item.dim - 1) % 7]
+            };
+        });
+    });
+
     describe('.now()', function () {
         it('should be the current time', function () {
             var before = (new Date()).getTime();
@@ -28,7 +121,7 @@ describe('Date', function () {
 
     describe('constructor', function () {
         it('works with standard formats', function () {
-                                                                               //    Chrome 19     Opera 12      Firefox 11    IE 9          Safari 5.1.1
+            //    Chrome 19     Opera 12      Firefox 11    IE 9          Safari 5.1.1
             expect(+new Date('2012-12-31T23:59:59.000Z')).toBe(1356998399000); //    1356998399000 1356998399000 1356998399000 1356998399000 1356998399000
             expect(+new Date('2012-04-04T05:02:02.170Z')).toBe(1333515722170); //    1333515722170 1333515722170 1333515722170 1333515722170 1333515722170
             expect(+new Date('2012-04-04T05:02:02.170999Z')).toBe(1333515722170); // 1333515722170 1333515722170 1333515722170 1333515722170 1333515722170
@@ -40,39 +133,48 @@ describe('Date', function () {
 
             // https://github.com/es-shims/es5-shim/issues/80 Safari bug with leap day
             expect(new Date('2034-03-01T00:00:00.000Z') -
-                        new Date('2034-02-27T23:59:59.999Z')).toBe(86400001); //          86400001      86400001      86400001      86400001             1
+                new Date('2034-02-27T23:59:59.999Z')).toBe(86400001); //          86400001      86400001      86400001      86400001             1
 
         });
 
         ifSupportsDescriptorsIt('is not enumerable', function () {
-          expect(Object.keys(new Date())).not.toContain('constructor');
+            expect(Object.keys(new Date())).not.toContain('constructor');
         });
 
         it('works as a function', function () {
-          var zeroDate = Date(0);
-          expect(zeroDate).toBe(String(zeroDate));
-          var value = Date(1441705534578);
-          expect(value).toBe(String(value));
+            var zeroDate = Date(0);
+            expect(zeroDate).toBe(String(zeroDate));
+            var value = Date(1441705534578);
+            expect(value).toBe(String(value));
         });
 
         it('fixes this Safari 8/9 bug', function () {
-          var offset = new Date(1970).getTimezoneOffset() * 60e3;
-
-          var timestamp = 2147483647; // Math.pow(2, 31) - 1
-          var date = new Date(1970, 0, 1, 0, 0, 0, timestamp);
-          var expectedTimestamp = timestamp + offset;
-          expect(date.getTime()).toBe(expectedTimestamp);
-
-          var brokenTimestamp = 2147483648; // Math.pow(2, 31)
-          var brokenDate = new Date(1970, 0, 1, 0, 0, 0, brokenTimestamp);
-          var expectedBrokenTimestamp = brokenTimestamp + offset;
-          expect(brokenDate.getTime()).toBe(expectedBrokenTimestamp); // NaN in Safari 8/9
+            var offset = new Date(1970).getTimezoneOffset() * 60e3;
+
+            var timestamp = 2147483647; // Math.pow(2, 31) - 1
+            var date = new Date(1970, 0, 1, 0, 0, 0, timestamp);
+            var expectedTimestamp = timestamp + offset;
+            expect(date.getTime()).toBe(expectedTimestamp);
+
+            var brokenTimestamp = 2147483648; // Math.pow(2, 31)
+            var brokenDate = new Date(1970, 0, 1, 0, 0, 0, brokenTimestamp);
+            var expectedBrokenTimestamp = brokenTimestamp + offset;
+            expect(brokenDate.getTime()).toBe(expectedBrokenTimestamp); // NaN in Safari 8/9
+
+            var veryBrokenTS = 1435734000000;
+            var veryBrokenDate = new Date(1970, 0, 1, 0, 0, 0, veryBrokenTS);
+            var largeDate = new Date('Wed Jul 01 2015 07:00:00 GMT-0700 (PDT)');
+            var expectedVeryBrokenTS = veryBrokenTS + (largeDate.getTimezoneOffset() * 60e3);
+            expect(veryBrokenDate.getTime()).toBe(expectedVeryBrokenTS); // NaN in Safari 8/9
+        });
 
-          var veryBrokenTS = 1435734000000;
-          var veryBrokenDate = new Date(1970, 0, 1, 0, 0, 0, veryBrokenTS);
-          var largeDate = new Date('Wed Jul 01 2015 07:00:00 GMT-0700 (PDT)');
-          var expectedVeryBrokenTS = veryBrokenTS + (largeDate.getTimezoneOffset() * 60e3);
-          expect(veryBrokenDate.getTime()).toBe(expectedVeryBrokenTS); // NaN in Safari 8/9
+        it('works with a Date object', function () {
+            var date = new Date(1456297712984);
+            var copiedDate = new Date(date);
+            expect(date).not.toBe(copiedDate);
+            expect(copiedDate.getTime()).toBe(date.getTime());
+            expect(+copiedDate).toBe(+date);
+            expect(String(copiedDate)).toBe(String(date));
         });
     });
 
@@ -80,11 +182,11 @@ describe('Date', function () {
         // TODO: Write the rest of the test.
 
         ifSupportsDescriptorsIt('is not enumerable', function () {
-          expect(Object.getOwnPropertyDescriptor(Date, 'parse').enumerable).toBe(false);
+            expect(Object.getOwnPropertyDescriptor(Date, 'parse').enumerable).toBe(false);
         });
 
         it('should be an invalid date', function () {
-                                                                        //            Chrome 19     Opera 12      Firefox 11    IE 9          Safari 5.1.1
+            //            Chrome 19     Opera 12      Firefox 11    IE 9          Safari 5.1.1
             expect(Date.parse('2012-11-31T23:59:59.000Z')).toBeFalsy(); //            1354406399000 NaN           NaN           1354406399000 NaN
             expect(Date.parse('2012-12-31T23:59:60.000Z')).toBeFalsy(); //            NaN           NaN           NaN           NaN           1356998400000
             expect(Date.parse('2012-04-04T24:00:00.500Z')).toBeFalsy(); //            NaN           NaN           1333584000500 1333584000500 NaN
@@ -102,7 +204,7 @@ describe('Date', function () {
 
         it('should work', function () {
             var dates = {
-                                                           //    Chrome 19     Opera 12      Firefox 11    IE 9          Safari 5.1.1  Safari 8
+                //    Chrome 19     Opera 12      Firefox 11    IE 9          Safari 5.1.1  Safari 8
                 '2012-12-31T23:59:59.000Z': 1356998399000, //    1356998399000 1356998399000 1356998399000 1356998399000 1356998399000 1356998399000
                 '2012-04-04T05:02:02.170Z': 1333515722170, //    1333515722170 1333515722170 1333515722170 1333515722170 1333515722170 1333515722170
                 '2012-04-04T05:02:02.170999Z': 1333515722170, // 1333515722170 1333515722170 1333515722170 1333515722170 1333515722170 1333515722170.999
@@ -120,7 +222,7 @@ describe('Date', function () {
 
             // https://github.com/es-shims/es5-shim/issues/80 Safari bug with leap day
             expect(Date.parse('2034-03-01T00:00:00.000Z') -
-                        Date.parse('2034-02-27T23:59:59.999Z')).toBe(86400001); //         86400001      86400001      86400001      86400001             1
+                Date.parse('2034-02-27T23:59:59.999Z')).toBe(86400001); //         86400001      86400001      86400001      86400001             1
 
         });
 
@@ -130,7 +232,7 @@ describe('Date', function () {
         });
 
         it('should support extended years', function () {
-                                                                               //    Chrome 19     Opera 12      Firefox 11    IE 9          Safari 5.1.1
+            //    Chrome 19     Opera 12      Firefox 11    IE 9          Safari 5.1.1
             expect(Date.parse('0000-01-01T00:00:00.000Z')).toBe(-621672192e5); //   -621672192e5  -621672192e5  -621672192e5  -621672192e5  -621672192e5
             expect(Date.parse('0001-01-01T00:00:00Z')).toBe(-621355968e5); //       -621355968e5  -621355968e5  -621355968e5   8.64e15      -621355968e5
             expect(Date.parse('+275760-09-13T00:00:00.000Z')).toBe(8.64e15); //      8.64e15       NaN           8.64e15       8.64e15       8.64e15
@@ -143,7 +245,7 @@ describe('Date', function () {
         });
 
         it('works with timezone offsets', function () {
-                                                                                   //  Chrome 19   Opera 12     Firefox 11   IE 9             Safari 5.1.1
+            //  Chrome 19   Opera 12     Firefox 11   IE 9             Safari 5.1.1
             expect(Date.parse('2012-01-29T12:00:00.000+01:00')).toBe(132783480e4); //  132783480e4 132783480e4  132783480e4  132783480e4      132783480e4
             expect(Date.parse('2012-01-29T12:00:00.000-00:00')).toBe(132783840e4); //  132783840e4 132783840e4  132783840e4  132783840e4      132783840e4
             expect(Date.parse('2012-01-29T12:00:00.000+00:00')).toBe(132783840e4); //  132783840e4 132783840e4  132783840e4  132783840e4      132783840e4
@@ -211,14 +313,43 @@ describe('Date', function () {
     describe('#getUTCDate()', function () {
         it('should return the right value for negative dates', function () {
             // Opera 10.6/11.61/Opera 12 bug
-            expect(new Date(-3509827334573292).getUTCDate()).toBe(1);
+            negativeDate.forEach(function (item) {
+                item.dates.forEach(function (date, index) {
+                    expect(date.getUTCDate()).toBe(item.days[index], date);
+                });
+            });
+        });
+    });
+
+    describe('#getUTCDay()', function () {
+        it('should return the right value for negative dates', function () {
+            negativeDate.forEach(function (item) {
+                item.dates.forEach(function (date, index) {
+                    expect(date.getUTCDay()).toBe(item.getUTCDay[index]);
+                });
+            });
+        });
+    });
+
+    describe('#getUTCFullYear()', function () {
+        it('should return the right value for negative dates', function () {
+            // Opera 10.6/11.61/Opera 12 bug
+            negativeDate.forEach(function (item) {
+                item.dates.forEach(function (date) {
+                    expect(date.getUTCFullYear()).toBe(-109252);
+                });
+            });
         });
     });
 
     describe('#getUTCMonth()', function () {
         it('should return the right value for negative dates', function () {
             // Opera 10.6/11.61/Opera 12 bug
-            expect(new Date(-3509827334573292).getUTCMonth()).toBe(0);
+            negativeDate.forEach(function (item, index) {
+                item.dates.forEach(function (date) {
+                    expect(date.getUTCMonth()).toBe(index);
+                });
+            });
         });
 
         it('should return correct values', function () {
@@ -227,6 +358,133 @@ describe('Date', function () {
         });
     });
 
+    describe('#getUTCHours()', function () {
+        it('should return the right value for negative dates', function () {
+            negativeDate.forEach(function (item) {
+                item.dates.forEach(function (date) {
+                    expect(date.getUTCHours()).toBe(11);
+                });
+            });
+        });
+    });
+
+    describe('#getUTCMinutes()', function () {
+        it('should return the right value for negative dates', function () {
+            negativeDate.forEach(function (item) {
+                item.dates.forEach(function (date) {
+                    expect(date.getUTCMinutes()).toBe(59);
+                });
+            });
+        });
+    });
+
+    describe('#getUTCSeconds()', function () {
+        it('should return the right value for negative dates', function () {
+            negativeDate.forEach(function (item) {
+                item.dates.forEach(function (date) {
+                    expect(date.getUTCSeconds()).toBe(59);
+                });
+            });
+        });
+    });
+
+    describe('#getUTCMilliseconds()', function () {
+        it('should return the right value for negative dates', function () {
+            // Opera 10.6/11.61/Opera 12 bug
+            negativeDate.forEach(function (item) {
+                item.dates.forEach(function (date) {
+                    expect(date.getUTCMilliseconds()).toBe(708);
+                });
+            });
+        });
+    });
+
+    describe('#getDate()', function () {
+        it('should return the right value for negative dates', function () {
+            negativeDate.forEach(function (item) {
+                item.dates.forEach(function (date, index) {
+                    expect(date.getDate()).toBe(item.days[index]);
+                });
+            });
+        });
+    });
+
+    describe('#getDay()', function () {
+        it('should return the right value for negative dates', function () {
+            negativeDate.forEach(function (item) {
+                item.dates.forEach(function (date, index) {
+                    expect(date.getDay()).toBe(item.getDay[index]);
+                });
+            });
+        });
+    });
+
+    describe('#getFullYear()', function () {
+        it('should return the right value for negative dates', function () {
+            // Opera 10.6/11.61/Opera 12 bug
+            negativeDate.forEach(function (item) {
+                item.dates.forEach(function (date) {
+                    expect(date.getFullYear()).toBe(-109252);
+                });
+            });
+        });
+    });
+
+    describe('#getMonth()', function () {
+        it('should return the right value for negative dates', function () {
+            // Opera 10.6/11.61/Opera 12 bug
+            negativeDate.forEach(function (item, index) {
+                item.dates.forEach(function (date) {
+                    expect(date.getMonth()).toBe(index);
+                });
+            });
+        });
+    });
+
+    describe('#getHours()', function () {
+        it('should return the right value for negative dates', function () {
+            negativeDate.forEach(function (item) {
+                item.dates.forEach(function (date) {
+                    expect(date.getHours() + Math.floor(date.getTimezoneOffset() / 60)).toBe(11);
+                });
+            });
+        });
+    });
+
+    describe('#getMinutes()', function () {
+        it('should return the right value for negative dates', function () {
+            negativeDate.forEach(function (item) {
+                item.dates.forEach(function (date) {
+                    var off = date.getTimezoneOffset();
+                    var offHours = Math.floor(off / 60);
+                    var offMins = off - offHours * 60;
+                    expect(date.getMinutes() + offMins).toBe(59);
+                });
+            });
+        });
+    });
+
+    describe('#getSeconds()', function () {
+        it('should return the right value for negative dates', function () {
+            negativeDate.forEach(function (item) {
+                item.dates.forEach(function (date) {
+                    expect(date.getSeconds()).toBe(59);
+                });
+            });
+        });
+    });
+
+    describe('#getMilliseconds()', function () {
+        it('should return the right value for negative dates', function () {
+            // Opera 10.6/11.61/Opera 12 bug
+            negativeDate.forEach(function (item) {
+                item.dates.forEach(function (date) {
+                    expect(date.getMilliseconds()).toBe(708);
+                });
+            });
+        });
+    });
+
     describe('#toISOString()', function () {
         // TODO: write the rest of the test.
 
@@ -236,33 +494,59 @@ describe('Date', function () {
         });
 
         it('should return correct dates', function () {
-            expect(new Date(-1).toISOString()).toBe('1969-12-31T23:59:59.999Z');// Safari 5.1.5 "1969-12-31T23:59:59.-01Z"
-            expect(new Date(-3509827334573292).toISOString()).toBe('-109252-01-01T10:37:06.708Z'); // Opera 11.61/Opera 12 bug with Date#getUTCMonth
+            expect(new Date(-1).toISOString()).toBe('1969-12-31T23:59:59.999Z'); // Safari 5.1.5 "1969-12-31T23:59:59.-01Z"
+            negativeDate.forEach(function (item, index) {
+                var m = index + 1;
+                item.dates.forEach(function (date, idx) {
+                    var d = item.days[idx];
+                    expect(date.toISOString()).toBe('-109252-' + (m < 10 ? '0' + m : m) + '-' + (d < 10 ? '0' + d : d) + 'T11:59:59.708Z'); // Opera 11.61/Opera 12 bug with Date#getUTCMonth
+                });
+            });
         });
 
     });
 
+    describe('#toUTCString()', function () {
+        it('should return correct dates', function () {
+            expect(new Date(-1509842289600292).toUTCString()).toBe('Mon, 01 Jan -45875 11:59:59 GMT');
+        });
+    });
+
+    describe('#toDateString()', function () {
+        it('should return correct dates', function () {
+            expect(new Date(-1509842289600292).toDateString()).toBe('Mon Jan 01 -45875');
+        });
+    });
+
+    describe('#toString()', function () {
+        it('should return correct dates', function () {
+            var actual = new Date(1449662400000).toString();
+            var re = /^Wed Dec 09 2015 \d\d:\d\d:\d\d GMT[-\+]\d\d\d\d(?: |$)/;
+            expect(re.test(actual)).toBe(true, actual);
+        });
+    });
+
     describe('#toJSON()', function () {
 
         // Opera 11.6x/12 bug
         it('should call toISOString', function () {
-          var date = new Date(0);
-          date.toISOString = function () {
-            return 1;
-          };
-          expect(date.toJSON()).toBe(1);
+            var date = new Date(0);
+            date.toISOString = function () {
+                return 1;
+            };
+            expect(date.toJSON()).toBe(1);
         });
 
         it('should return null for not finite dates', function () {
-          var date = new Date(NaN),
-              json;
-          try {
-            json = date.toJSON();
-          } catch (e) {
-            /* invalid json */
-            expect(e).not.toEqual(jasmine.any(Error));
-          }
-          expect(json).toBe(null);
+            var date = new Date(NaN),
+                json;
+            try {
+                json = date.toJSON();
+            } catch (e) {
+                /* invalid json */
+                expect(e).not.toEqual(jasmine.any(Error));
+            }
+            expect(json).toBe(null);
         });
 
         it('should return the isoString when stringified', function () {
diff --git a/tests/spec/s-global.js b/tests/spec/s-global.js
index 4c0c97a..4fb5cf2 100644
--- a/tests/spec/s-global.js
+++ b/tests/spec/s-global.js
@@ -7,6 +7,13 @@ describe('global methods', function () {
     var functionsHaveNames = foo.name === 'foo';
     var ifFunctionsHaveNamesIt = functionsHaveNames ? it : xit;
 
+    var is = function (x, y) {
+        if (x === 0 && y === 0) {
+            return 1 / x === 1 / y;
+        }
+        return x === y;
+    };
+
     describe('parseInt', function () {
         /* eslint-disable radix */
 
@@ -62,4 +69,15 @@ describe('global methods', function () {
         });
         /* eslint-enable radix */
     });
+
+    describe('parseFloat()', function () {
+        it('works with zeroes', function () {
+            expect(is(parseFloat('0'), 0) ? '+0' : '-0').toBe('+0');
+            expect(is(parseFloat(' 0'), 0) ? '+0' : '-0').toBe('+0');
+            expect(is(parseFloat('+0'), 0) ? '+0' : '-0').toBe('+0');
+            expect(is(parseFloat(' +0'), 0) ? '+0' : '-0').toBe('+0');
+            expect(is(parseFloat('-0'), -0) ? '-0' : '+0').toBe('-0');
+            expect(is(parseFloat(' -0'), -0) ? '-0' : '+0').toBe('-0');
+        });
+    });
 });
diff --git a/tests/spec/s-object.js b/tests/spec/s-object.js
index 3065c66..f46a848 100644
--- a/tests/spec/s-object.js
+++ b/tests/spec/s-object.js
@@ -142,7 +142,10 @@ describe('Object', function () {
           var windowItemKeys, exception;
           var blacklistedKeys = ['window', 'console', 'parent', 'self', 'frame', 'frames', 'frameElement', 'external'];
           if (supportsDescriptors) {
-              Object.defineProperty(window, 'thrower', { configurable: true, get: function () { throw new RangeError('thrower!'); } });
+              Object.defineProperty(window, 'thrower', {
+                  configurable: true,
+                  get: function () { throw new RangeError('thrower!'); }
+              });
           }
           for (var k in window) {
               windowItemKeys = exception = void 0;
diff --git a/tests/spec/s-string.js b/tests/spec/s-string.js
index 8f15157..74439c5 100644
--- a/tests/spec/s-string.js
+++ b/tests/spec/s-string.js
@@ -228,6 +228,10 @@ describe('String', function () {
                 expect('a b c d'.split(/ /, Infinity)).toEqual([]);
             });
         });
+
+        it('works with the second argument', function () {
+            expect('a b'.split(/ /, 1)).toEqual(['a']);
+        });
     });
 
     describe('#indexOf()', function () {

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-es5-shim.git



More information about the Pkg-javascript-commits mailing list