[Pkg-javascript-commits] [node-es5-shim] 01/03: Imported Upstream version 4.4.1

Julien Puydt julien.puydt at laposte.net
Sat Jan 2 13:30:15 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 4024950389c1ffc3cd8c8196cad78f2c4abc4476
Author: Julien Puydt <julien.puydt at laposte.net>
Date:   Sat Jan 2 14:20:19 2016 +0100

    Imported Upstream version 4.4.1
---
 .eslintrc                |   3 +-
 .jscs.json               |  26 +-
 .travis.yml              |   9 +-
 CHANGES                  |  46 +++
 README.md                |  11 +-
 component.json           |   2 +-
 es5-sham.js              |   8 +-
 es5-sham.map             |   2 +-
 es5-sham.min.js          |   4 +-
 es5-shim.js              | 413 +++++++++++++++++------
 es5-shim.map             |   2 +-
 es5-shim.min.js          |   4 +-
 package.json             |  15 +-
 tests/index.html         |  10 +-
 tests/index.min.html     |   8 +-
 tests/native.html        |  10 +-
 tests/spec/s-array.js    | 852 +++++++++++++++++++++++++++++++++++++++++------
 tests/spec/s-date.js     |  21 +-
 tests/spec/s-error.js    |  50 +++
 tests/spec/s-function.js |   4 +-
 tests/spec/s-global.js   |  20 +-
 tests/spec/s-number.js   |  24 +-
 tests/spec/s-object.js   |  69 ++--
 tests/spec/s-regexp.js   |  27 ++
 tests/spec/s-string.js   |  36 +-
 25 files changed, 1361 insertions(+), 315 deletions(-)

diff --git a/.eslintrc b/.eslintrc
index 2cea9de..d362d1d 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -14,7 +14,7 @@
 		"max-statements": [1, 30],
 		"new-cap": [2, { "capIsNewExceptions": ["ToInteger", "ToObject", "ToPrimitive", "ToUint32"] }],
 		"no-constant-condition": [1],
-		"no-extend-native": [2, {"exceptions": ["Date"]}],
+		"no-extend-native": [2, {"exceptions": ["Date", "Error", "RegExp"]}],
 		"no-extra-parens": [0],
 		"no-extra-semi": [1],
 		"no-func-assign": [1],
@@ -27,6 +27,7 @@
 		"no-magic-numbers": [0],
 		"no-native-reassign": [2, {"exceptions": ["Date", "parseInt"]}],
 		"no-new-func": [1],
+		"no-plusplus": [1],
 		"no-restricted-syntax": [2, "ContinueStatement", "DebuggerStatement", "LabeledStatement", "WithStatement"],
 		"no-shadow": [1],
 		"no-unused-vars": [1, { "vars": "all", "args": "after-used" }],
diff --git a/.jscs.json b/.jscs.json
index bd4d449..629794b 100644
--- a/.jscs.json
+++ b/.jscs.json
@@ -9,13 +9,17 @@
 
 	"disallowIdentifierNames": [],
 
-	"requireCurlyBraces": ["if", "else", "for", "while", "do", "try", "catch"],
+	"requireCurlyBraces": {
+		"allExcept": [],
+		"keywords": ["if", "else", "for", "while", "do", "try", "catch"]
+	},
 
 	"requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch", "function"],
 
 	"disallowSpaceAfterKeywords": [],
 
 	"disallowSpaceBeforeComma": true,
+	"disallowSpaceAfterComma": false,
 	"disallowSpaceBeforeSemicolon": true,
 
 	"disallowNodeTypes": [
@@ -126,7 +130,23 @@
 
 	"disallowNestedTernaries": { "maxLevel": 7 },
 
-	"requireSpaceAfterComma": true,
-	"requireAlignedMultilineParams": false
+	"requireSpaceAfterComma": { "allExcept": ["trailing"] },
+	"requireAlignedMultilineParams": false,
+
+	"requireSpacesInGenerator": {
+		"afterStar": true
+	},
+
+	"disallowSpacesInGenerator": {
+		"beforeStar": true
+	},
+
+	"disallowVar": false,
+
+	"requireArrayDestructuring": false,
+
+	"requireEnhancedObjectLiterals": false,
+
+	"requireObjectDestructuring": false
 }
 
diff --git a/.travis.yml b/.travis.yml
index 324496c..95aa579 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,7 @@
 language: node_js
 node_js:
+  - "5.1"
+  - "5.0"
   - "4.2"
   - "4.1"
   - "4.0"
@@ -30,11 +32,15 @@ node_js:
   - "0.6"
   - "0.4"
 before_install:
-  - '[ "${TRAVIS_NODE_VERSION}" = "0.6" ] || npm install -g npm at 1.4.28 && npm install -g npm'
+  - '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'
 sudo: false
 matrix:
   fast_finish: true
   allow_failures:
+    - node_js: "5.0"
     - node_js: "4.1"
     - node_js: "4.0"
     - node_js: "iojs-v3.2"
@@ -55,6 +61,5 @@ matrix:
     - node_js: "iojs-v1.0"
     - node_js: "0.11"
     - node_js: "0.9"
-    - node_js: "0.8"
     - node_js: "0.6"
     - node_js: "0.4"
diff --git a/CHANGES b/CHANGES
index 43fed63..c96bd0d 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,49 @@
+4.4.1
+  - [Fix] ensure that IE 11 in compatibility mode doesn't throw (#370)
+  - [Docs] add missing shimmed things
+
+4.4.0
+  - [New] Detect and patch `RegExp#toString` in IE 8, which returns flags in the wrong order (#364)
+  - [Fix] Patch `Array#sort` on {Chrome, Safari, IE < 9, FF 4} that throws improperly, per ES5 (#354)
+  - [Fix] In IE 6, `window.external` makes `Object.keys` throw
+  - [Fix] `Array#slice`: boxed string access on IE <= 8 (#349)
+  - [Fix] `Array#join`: fix IE 6-8 join called on string literal (#352)
+  - [Fix] Ensure that `Error#message` and `Error#name` are non-enumerable (#358)
+  - [Fix: sham] `Object.getOwnPropertyDescriptor`: In Opera 11.6, `propertyIsEnumerable` is a nonshadowable global, like `toString`
+  - [Robustness] Use a bound form of `Array#slice.call`
+  - [Tests] Properly check for descriptor support in IE <= 8
+  - [Tests] on `node` `v5.1`
+  - [Tests] Add `Array#slice` tests (#346)
+  - [Dev Deps] update `uglify-js`, `eslint`, `jscs`, `uglify-js`, `semver`
+  - [Docs] Fix broken UMD links (#344)
+
+4.3.1
+  - [Fix] `String#split`: revert part of dcce96ae21185a69d2d40e67416e7496b73e8e47 which broke in older browsers (#342)
+  - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `jscs`
+  - [Tests] Firefox allows `Number#toPrecision` values of [1,100], which the spec permits
+
+4.3.0
+  - [New] `Array#push`: in IE <= 7, `Array#push` was not generic (#336)
+  - [New] `Array#push` in Opera `10.6` has a super weird bug when pushing `undefined`
+  - [New] `Array#join`: In IE <= 7, passing `undefined` didn't use the default separator (#333)
+  - [New] `Error#toString`: prints out the proper message in IE 7 and below (#334)
+  - [New] `Number#toPrecision`: IE 7 and below incorrectly throw when an explicit `undefined` precision is passed (#340)
+  - [Fix] `String#lastIndexOf`: ensure the correct length in IE 8
+  - [Fix] ensure `parseInt` accepts negative and plus-prefixed hex values (#332)
+  - [Robustness] Use a bound `Array#push` instead of relying on `Function#call`
+  - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `jscs`
+  - [Tests] Add some conditionals to avoid impossible-to-fix test failures in IE 6-8, due to it being unable to distinguish between `undefined` and an absent index (#114)
+  - [Tests] Fix false negatives in IE 6-8 with jasmine comparing arrays to arraylikes (#114)
+  - [Tests] add additional `Array#shift` tests (#337)
+  - [Tests] Add additional `Array#splice` tests (#339)
+  - [Tests] Add `Array#pop` tests, just in case (#338)
+  - [Tests] include `global` tests in HTML test files
+  - [Tests] Make sure the HTML tests run with the right charset
+  - [Tests] ensure `node` `v0.8` tests stay passing.
+  - [Tests] Prevent nondeterminism in the tests - this sometime produced values that are one ms off
+  - [Tests] on `node` `v5.0`
+  - [Tests] fix npm upgrades for older nodes
+
 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`
diff --git a/README.md b/README.md
index 81d6a87..12549e1 100644
--- a/README.md
+++ b/README.md
@@ -35,9 +35,13 @@ simply `npm install` and `npm test`.
 * Array.prototype.indexOf
 * Array.prototype.lastIndexOf
 * Array.prototype.map
+* Array.prototype.slice
 * Array.prototype.some
+* Array.prototype.sort
 * Array.prototype.reduce
 * Array.prototype.reduceRight
+* Array.prototype.push
+* Array.prototype.join
 * Array.isArray
 * Date.now
 * Date.prototype.toJSON
@@ -48,14 +52,20 @@ simply `npm install` and `npm test`.
     * :warning: Caveat: bound functions don't have checks in ``call`` and
       ``apply`` to avoid executing as a constructor.
 * Number.prototype.toFixed
+* Number.prototype.toPrecision
 * Object.keys
 * String.prototype.split
 * String.prototype.trim
+* String.prototype.lastIndexOf
 * String.prototype.replace
     * Firefox (through v29) natively handles capturing groups incorrectly.
 * Date.parse (for ISO parsing)
 * Date.prototype.toISOString
 * parseInt
+* Error.prototype.toString
+* Error.prototype.name
+* Error.prototype.message
+* RegExp.prototype.toString
 
 ## Shams
 
@@ -164,4 +174,3 @@ simply `npm install` and `npm test`.
 [dev-deps-svg]: https://david-dm.org/es-shims/es5-shim/dev-status.svg
 [dev-deps-url]: https://david-dm.org/es-shims/es5-shim#info=devDependencies
 [npm-badge-png]: https://nodei.co/npm/es5-shim.png?downloads=true&stars=true
-
diff --git a/component.json b/component.json
index 60a6d6e..afc39c4 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.2.0",
+    "version": "v4.4.1",
     "keywords": [
         "shim",
         "es5",
diff --git a/es5-sham.js b/es5-sham.js
index 9a15cbd..bc21634 100644
--- a/es5-sham.js
+++ b/es5-sham.js
@@ -10,7 +10,7 @@
 ;
 
 // UMD (Universal Module Definition)
-// see https://github.com/umdjs/umd/blob/master/returnExports.js
+// see https://github.com/umdjs/umd/blob/master/templates/returnExports.js
 (function (root, factory) {
     'use strict';
 
@@ -29,10 +29,10 @@
   }
 }(this, function () {
 
-var call = Function.prototype.call;
+var call = Function.call;
 var prototypeOfObject = Object.prototype;
 var owns = call.bind(prototypeOfObject.hasOwnProperty);
-var propertyIsEnumerable = call.bind(prototypeOfObject.propertyIsEnumerable);
+var isEnumerable = call.bind(prototypeOfObject.propertyIsEnumerable);
 var toStr = call.bind(prototypeOfObject.toString);
 
 // If JS engine supports accessors creating shortcuts.
@@ -131,7 +131,7 @@ if (!Object.getOwnPropertyDescriptor || getOwnPropertyDescriptorFallback) {
         // If object has a property then it's for sure `configurable`, and
         // probably `enumerable`. Detect enumerability though.
         descriptor = {
-            enumerable: propertyIsEnumerable(object, property),
+            enumerable: isEnumerable(object, property),
             configurable: true
         };
 
diff --git a/es5-sham.map b/es5-sham.map
index f37dfcb..3ed2a57 100644
--- a/es5-sham.map
+++ b/es5-sham.map
@@ -1 +1 @@
-{"version":3,"sources":["es5-sham.js"],"names":["root","factory","define","amd","exports","module","returnExports","this","call","Function","prototype","prototypeOfObject","Object","owns","bind","hasOwnProperty","propertyIsEnumerable","toStr","toString","defineGetter","defineSetter","lookupGetter","lookupSetter","supportsAccessors","__defineGetter__","__defineSetter__","__lookupGetter__","__lookupSetter__","getPrototypeOf","object","proto","__proto__","constructor","doesGetOwnPropertyDes [...]
\ No newline at end of file
+{"version":3,"sources":["es5-sham.js"],"names":["root","factory","define","amd","exports","module","returnExports","this","call","Function","prototypeOfObject","Object","prototype","owns","bind","hasOwnProperty","isEnumerable","propertyIsEnumerable","toStr","toString","defineGetter","defineSetter","lookupGetter","lookupSetter","supportsAccessors","__defineGetter__","__defineSetter__","__lookupGetter__","__lookupSetter__","getPrototypeOf","object","proto","__proto__","constructor","doesGe [...]
\ No newline at end of file
diff --git a/es5-sham.min.js b/es5-sham.min.js
index 415504b..389699d 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.2.0/LICENSE
+ * see https://github.com/es-shims/es5-shim/blob/v4.4.1/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.prototype.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.__lookupS [...]
+(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 5daa667..6022eee 100644
--- a/es5-shim.js
+++ b/es5-shim.js
@@ -10,7 +10,7 @@
 ;
 
 // UMD (Universal Module Definition)
-// see https://github.com/umdjs/umd/blob/master/returnExports.js
+// see https://github.com/umdjs/umd/blob/master/templates/returnExports.js
 (function (root, factory) {
     'use strict';
 
@@ -56,6 +56,7 @@ var array_push = ArrayPrototype.push;
 var array_unshift = ArrayPrototype.unshift;
 var array_concat = ArrayPrototype.concat;
 var call = FunctionPrototype.call;
+var apply = FunctionPrototype.apply;
 var max = Math.max;
 var min = Math.min;
 
@@ -68,19 +69,18 @@ var isRegex; /* inlined from https://npmjs.com/is-regex */ var regexExec = RegEx
 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; };
 
 /* inlined from http://npmjs.com/define-properties */
+var supportsDescriptors = $Object.defineProperty && (function () {
+    try {
+        var obj = {};
+        $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;
+    }
+}());
 var defineProperties = (function (has) {
-  var supportsDescriptors = $Object.defineProperty && (function () {
-      try {
-          var obj = {};
-          $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;
-      }
-  }());
-
-  // Define configurable, writable and non-enumerable props
+  // Define configurable, writable, and non-enumerable props
   // if they don't exist.
   var defineProperty;
   if (supportsDescriptors) {
@@ -163,7 +163,6 @@ var ES = {
     // http://es5.github.com/#x9.9
     /* replaceable with https://npmjs.com/package/es-abstract ES5.ToObject */
     ToObject: function (o) {
-        /* jshint eqnull: true */
         if (o == null) { // this matches both null and undefined
             throw new TypeError("can't convert " + o + ' to object');
         }
@@ -321,12 +320,17 @@ defineProperties(FunctionPrototype, {
 });
 
 // _Please note: Shortcuts are defined after `Function.prototype.bind` as we
-// us it in defining shortcuts.
+// use it in defining shortcuts.
 var owns = call.bind(ObjectPrototype.hasOwnProperty);
 var toStr = call.bind(ObjectPrototype.toString);
+var arraySlice = call.bind(array_slice);
+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 isEnum = call.bind(ObjectPrototype.propertyIsEnumerable);
+var arraySort = call.bind(ArrayPrototype.sort);
 
 //
 // Array
@@ -395,7 +399,7 @@ var properlyBoxesContext = function properlyBoxed(method) {
 };
 
 defineProperties(ArrayPrototype, {
-    forEach: function forEach(callbackfn /*, thisArg*/) {
+    forEach: function forEach(callbackfn/*, thisArg*/) {
         var object = ES.ToObject(this);
         var self = splitString && isString(this) ? strSplit(this, '') : object;
         var i = -1;
@@ -460,7 +464,7 @@ defineProperties(ArrayPrototype, {
 // http://es5.github.com/#x15.4.4.20
 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter
 defineProperties(ArrayPrototype, {
-    filter: function filter(callbackfn /*, thisArg*/) {
+    filter: function filter(callbackfn/*, thisArg*/) {
         var object = ES.ToObject(this);
         var self = splitString && isString(this) ? strSplit(this, '') : object;
         var length = ES.ToUint32(self.length);
@@ -480,7 +484,7 @@ defineProperties(ArrayPrototype, {
             if (i in self) {
                 value = self[i];
                 if (typeof T === 'undefined' ? callbackfn(value, i, object) : callbackfn.call(T, value, i, object)) {
-                    array_push.call(result, value);
+                    push(result, value);
                 }
             }
         }
@@ -492,7 +496,7 @@ defineProperties(ArrayPrototype, {
 // http://es5.github.com/#x15.4.4.16
 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every
 defineProperties(ArrayPrototype, {
-    every: function every(callbackfn /*, thisArg*/) {
+    every: function every(callbackfn/*, thisArg*/) {
         var object = ES.ToObject(this);
         var self = splitString && isString(this) ? strSplit(this, '') : object;
         var length = ES.ToUint32(self.length);
@@ -550,7 +554,7 @@ if (ArrayPrototype.reduce) {
     reduceCoercesToObject = typeof ArrayPrototype.reduce.call('es5', function (_, __, ___, list) { return list; }) === 'object';
 }
 defineProperties(ArrayPrototype, {
-    reduce: function reduce(callbackfn /*, initialValue*/) {
+    reduce: function reduce(callbackfn/*, initialValue*/) {
         var object = ES.ToObject(this);
         var self = splitString && isString(this) ? strSplit(this, '') : object;
         var length = ES.ToUint32(self.length);
@@ -653,7 +657,7 @@ defineProperties(ArrayPrototype, {
 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
 var hasFirefox2IndexOfBug = ArrayPrototype.indexOf && [0, 1].indexOf(1, 2) !== -1;
 defineProperties(ArrayPrototype, {
-    indexOf: function indexOf(searchElement /*, fromIndex */) {
+    indexOf: function indexOf(searchElement/*, fromIndex */) {
         var self = splitString && isString(this) ? strSplit(this, '') : ES.ToObject(this);
         var length = ES.ToUint32(self.length);
 
@@ -682,7 +686,7 @@ defineProperties(ArrayPrototype, {
 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf
 var hasFirefox2LastIndexOfBug = ArrayPrototype.lastIndexOf && [0, 1].lastIndexOf(0, -3) !== -1;
 defineProperties(ArrayPrototype, {
-    lastIndexOf: function lastIndexOf(searchElement /*, fromIndex */) {
+    lastIndexOf: function lastIndexOf(searchElement/*, fromIndex */) {
         var self = splitString && isString(this) ? strSplit(this, '') : ES.ToObject(this);
         var length = ES.ToUint32(self.length);
 
@@ -733,9 +737,9 @@ defineProperties(ArrayPrototype, {
         var args = arguments;
         this.length = max(ES.ToInteger(this.length), 0);
         if (arguments.length > 0 && typeof deleteCount !== 'number') {
-            args = array_slice.call(arguments);
+            args = arraySlice(arguments);
             if (args.length < 2) {
-                array_push.call(args, this.length - start);
+                push(args, this.length - start);
             } else {
                 args[1] = ES.ToInteger(deleteCount);
             }
@@ -782,7 +786,7 @@ defineProperties(ArrayPrototype, {
             k += 1;
         }
 
-        var items = array_slice.call(arguments, 2);
+        var items = arraySlice(arguments, 2);
         var itemCount = items.length;
         var to;
         if (itemCount < actualDeleteCount) {
@@ -826,6 +830,112 @@ defineProperties(ArrayPrototype, {
     }
 }, !spliceWorksWithLargeSparseArrays || !spliceWorksWithSmallSparseArrays);
 
+var originalJoin = ArrayPrototype.join;
+var hasStringJoinBug;
+try {
+    hasStringJoinBug = Array.prototype.join.call('123', ',') !== '1,2,3';
+} catch (e) {
+    hasStringJoinBug = true;
+}
+if (hasStringJoinBug) {
+    defineProperties(ArrayPrototype, {
+        join: function join(separator) {
+            var sep = typeof separator === 'undefined' ? ',' : separator;
+            return originalJoin.call(isString(this) ? strSplit(this, '') : this, sep);
+        }
+    }, hasStringJoinBug);
+}
+
+var hasJoinUndefinedBug = [1, 2].join(undefined) !== '1,2';
+if (hasJoinUndefinedBug) {
+    defineProperties(ArrayPrototype, {
+        join: function join(separator) {
+            var sep = typeof separator === 'undefined' ? ',' : separator;
+            return originalJoin.call(this, sep);
+        }
+    }, hasJoinUndefinedBug);
+}
+
+var pushShim = function push(item) {
+    var O = ES.ToObject(this);
+    var n = ES.ToUint32(O.length);
+    var i = 0;
+    while (i < arguments.length) {
+        O[n + i] = arguments[i];
+        i += 1;
+    }
+    O.length = n + i;
+    return n + i;
+};
+
+var pushIsNotGeneric = (function () {
+    var obj = {};
+    var result = Array.prototype.push.call(obj, undefined);
+    return result !== 1 || obj.length !== 1 || typeof obj[0] !== 'undefined' || !owns(obj, 0);
+}());
+defineProperties(ArrayPrototype, {
+    push: function push(item) {
+        if (isArray(this)) {
+            return array_push.apply(this, arguments);
+        }
+        return pushShim.apply(this, arguments);
+    }
+}, pushIsNotGeneric);
+
+// This fixes a very weird bug in Opera 10.6 when pushing `undefined
+var pushUndefinedIsWeird = (function () {
+    var arr = [];
+    var result = arr.push(undefined);
+    return result !== 1 || arr.length !== 1 || typeof arr[0] !== 'undefined' || !owns(arr, 0);
+}());
+defineProperties(ArrayPrototype, { push: pushShim }, pushUndefinedIsWeird);
+
+// ES5 15.2.3.14
+// http://es5.github.io/#x15.4.4.10
+// Fix boxed string bug
+defineProperties(ArrayPrototype, {
+    slice: function (start, end) {
+        var arr = isString(this) ? strSplit(this, '') : this;
+        return arraySliceApply(arr, arguments);
+    }
+}, splitString);
+
+var sortIgnoresNonFunctions = (function () {
+    try {
+        [1, 2].sort(null);
+        [1, 2].sort({});
+        return true;
+    } catch (e) { /**/ }
+    return false;
+}());
+var sortThrowsOnRegex = (function () {
+    // this is a problem in Firefox 4, in which `typeof /a/ === 'function'`
+    try {
+        [1, 2].sort(/a/);
+        return false;
+    } catch (e) { /**/ }
+    return true;
+}());
+var sortIgnoresUndefined = (function () {
+    // applies in IE 8, for one.
+    try {
+        [1, 2].sort(undefined);
+        return true;
+    } catch (e) { /**/ }
+    return false;
+}());
+defineProperties(ArrayPrototype, {
+    sort: function sort(compareFn) {
+        if (typeof compareFn === 'undefined') {
+            return arraySort(this);
+        }
+        if (!isCallable(compareFn)) {
+            throw new TypeError('Array.prototype.sort callback must be a function');
+        }
+        return arraySort(this, compareFn);
+    }
+}, sortIgnoresNonFunctions || !sortIgnoresUndefined || !sortThrowsOnRegex);
+
 //
 // Object
 // ======
@@ -851,7 +961,8 @@ var blacklistedKeys = {
     $frames: true,
     $frameElement: true,
     $webkitIndexedDB: true,
-    $webkitStorageInfo: true
+    $webkitStorageInfo: true,
+    $external: true
 };
 var hasAutomationEqualityBug = (function () {
     /* globals window */
@@ -916,14 +1027,14 @@ defineProperties($Object, {
         var skipProto = hasProtoEnumBug && isFn;
         if ((isStr && hasStringEnumBug) || isArgs) {
             for (var i = 0; i < object.length; ++i) {
-                array_push.call(theKeys, $String(i));
+                push(theKeys, $String(i));
             }
         }
 
         if (!isArgs) {
             for (var name in object) {
                 if (!(skipProto && name === 'prototype') && owns(object, name)) {
-                    array_push.call(theKeys, $String(name));
+                    push(theKeys, $String(name));
                 }
             }
         }
@@ -933,7 +1044,7 @@ defineProperties($Object, {
             for (var j = 0; j < dontEnumsLength; j++) {
                 var dontEnum = dontEnums[j];
                 if (!(skipConstructor && dontEnum === 'constructor') && owns(object, dontEnum)) {
-                    array_push.call(theKeys, dontEnum);
+                    push(theKeys, dontEnum);
                 }
             }
         }
@@ -953,7 +1064,7 @@ var originalKeys = $Object.keys;
 defineProperties($Object, {
     keys: function keys(object) {
         if (isArguments(object)) {
-            return originalKeys(array_slice.call(object));
+            return originalKeys(arraySlice(object));
         } else {
             return originalKeys(object);
         }
@@ -1009,8 +1120,8 @@ defineProperties(Date.prototype, {
         }
         // pad milliseconds to have three digits.
         return (
-            year + '-' + array_slice.call(result, 0, 2).join('-') +
-            'T' + array_slice.call(result, 2).join(':') + '.' +
+            year + '-' + arraySlice(result, 0, 2).join('-') +
+            'T' + arraySlice(result, 2).join(':') + '.' +
             strSlice('000' + this.getUTCMilliseconds(), -3) + 'Z'
         );
     }
@@ -1081,7 +1192,6 @@ if (doesNotParseY2KNewYear || acceptsInvalidDates || !supportsExtendedYears) {
     /* global Date: true */
     /* eslint-disable no-undef */
     var maxSafeUnsigned32Bit = Math.pow(2, 31) - 1;
-    var secondsWithinMaxSafeUnsigned32Bit = Math.floor(maxSafeUnsigned32Bit / 1e3);
     var hasSafariSignedIntBug = isActualNaN(new Date(1970, 0, 1, 0, 0, 0, maxSafeUnsigned32Bit + 1).getTime());
     Date = (function (NativeDate) {
     /* eslint-enable no-undef */
@@ -1322,91 +1432,104 @@ var toFixedHelpers = {
   }
 };
 
-defineProperties(NumberPrototype, {
-    toFixed: function toFixed(fractionDigits) {
-        var f, x, s, m, e, z, j, k;
-
-        // Test for NaN and round fractionDigits down
-        f = $Number(fractionDigits);
-        f = isActualNaN(f) ? 0 : Math.floor(f);
-
-        if (f < 0 || f > 20) {
-            throw new RangeError('Number.toFixed called with invalid number of decimals');
-        }
-
-        x = $Number(this);
-
-        if (isActualNaN(x)) {
-            return 'NaN';
-        }
+var toFixedShim = function toFixed(fractionDigits) {
+    var f, x, s, m, e, z, j, k;
 
-        // If it is too big or small, return the string value of the number
-        if (x <= -1e21 || x >= 1e21) {
-            return $String(x);
-        }
+    // Test for NaN and round fractionDigits down
+    f = $Number(fractionDigits);
+    f = isActualNaN(f) ? 0 : Math.floor(f);
 
-        s = '';
+    if (f < 0 || f > 20) {
+        throw new RangeError('Number.toFixed called with invalid number of decimals');
+    }
 
-        if (x < 0) {
-            s = '-';
-            x = -x;
-        }
+    x = $Number(this);
 
-        m = '0';
+    if (isActualNaN(x)) {
+        return 'NaN';
+    }
 
-        if (x > 1e-21) {
-            // 1e-21 < x < 1e21
-            // -70 < log2(x) < 70
-            e = toFixedHelpers.log(x * toFixedHelpers.pow(2, 69, 1)) - 69;
-            z = (e < 0 ? x * toFixedHelpers.pow(2, -e, 1) : x / toFixedHelpers.pow(2, e, 1));
-            z *= 0x10000000000000; // Math.pow(2, 52);
-            e = 52 - e;
+    // If it is too big or small, return the string value of the number
+    if (x <= -1e21 || x >= 1e21) {
+        return $String(x);
+    }
 
-            // -18 < e < 122
-            // x = z / 2 ^ e
-            if (e > 0) {
-                toFixedHelpers.multiply(0, z);
-                j = f;
+    s = '';
 
-                while (j >= 7) {
-                    toFixedHelpers.multiply(1e7, 0);
-                    j -= 7;
-                }
+    if (x < 0) {
+        s = '-';
+        x = -x;
+    }
 
-                toFixedHelpers.multiply(toFixedHelpers.pow(10, j, 1), 0);
-                j = e - 1;
+    m = '0';
+
+    if (x > 1e-21) {
+        // 1e-21 < x < 1e21
+        // -70 < log2(x) < 70
+        e = toFixedHelpers.log(x * toFixedHelpers.pow(2, 69, 1)) - 69;
+        z = (e < 0 ? x * toFixedHelpers.pow(2, -e, 1) : x / toFixedHelpers.pow(2, e, 1));
+        z *= 0x10000000000000; // Math.pow(2, 52);
+        e = 52 - e;
+
+        // -18 < e < 122
+        // x = z / 2 ^ e
+        if (e > 0) {
+            toFixedHelpers.multiply(0, z);
+            j = f;
+
+            while (j >= 7) {
+                toFixedHelpers.multiply(1e7, 0);
+                j -= 7;
+            }
 
-                while (j >= 23) {
-                    toFixedHelpers.divide(1 << 23);
-                    j -= 23;
-                }
+            toFixedHelpers.multiply(toFixedHelpers.pow(10, j, 1), 0);
+            j = e - 1;
 
-                toFixedHelpers.divide(1 << j);
-                toFixedHelpers.multiply(1, 1);
-                toFixedHelpers.divide(2);
-                m = toFixedHelpers.numToString();
-            } else {
-                toFixedHelpers.multiply(0, z);
-                toFixedHelpers.multiply(1 << (-e), 0);
-                m = toFixedHelpers.numToString() + strSlice('0.00000000000000000000', 2, 2 + f);
+            while (j >= 23) {
+                toFixedHelpers.divide(1 << 23);
+                j -= 23;
             }
+
+            toFixedHelpers.divide(1 << j);
+            toFixedHelpers.multiply(1, 1);
+            toFixedHelpers.divide(2);
+            m = toFixedHelpers.numToString();
+        } else {
+            toFixedHelpers.multiply(0, z);
+            toFixedHelpers.multiply(1 << (-e), 0);
+            m = toFixedHelpers.numToString() + strSlice('0.00000000000000000000', 2, 2 + f);
         }
+    }
 
-        if (f > 0) {
-            k = m.length;
+    if (f > 0) {
+        k = m.length;
 
-            if (k <= f) {
-                m = s + strSlice('0.0000000000000000000', 0, f - k + 2) + m;
-            } else {
-                m = s + strSlice(m, 0, k - f) + '.' + strSlice(m, k - f);
-            }
+        if (k <= f) {
+            m = s + strSlice('0.0000000000000000000', 0, f - k + 2) + m;
         } else {
-            m = s + m;
+            m = s + strSlice(m, 0, k - f) + '.' + strSlice(m, k - f);
         }
+    } else {
+        m = s + m;
+    }
+
+    return m;
+};
+defineProperties(NumberPrototype, { toFixed: toFixedShim }, hasToFixedBugs);
 
-        return m;
+var hasToPrecisionUndefinedBug = (function () {
+    try {
+        return 1.0.toPrecision(undefined) === '1';
+    } catch (e) {
+        return true;
+    }
+}());
+var originalToPrecision = NumberPrototype.toPrecision;
+defineProperties(NumberPrototype, {
+    toPrecision: function toPrecision(precision) {
+        return typeof precision === 'undefined' ? originalToPrecision.call(this) : originalToPrecision.call(this, precision);
     }
-}, hasToFixedBugs);
+}, hasToPrecisionUndefinedBug);
 
 //
 // String
@@ -1441,7 +1564,7 @@ if (
         var maxSafe32BitInt = Math.pow(2, 32) - 1;
 
         StringPrototype.split = function (separator, limit) {
-            var string = this;
+            var string = String(this);
             if (typeof separator === 'undefined' && limit === 0) {
                 return [];
             }
@@ -1460,7 +1583,6 @@ if (
                 // Make `global` and avoid `lastIndex` issues by working with a copy
                 separator2, match, lastIndex, lastLength;
             var separatorCopy = new RegExp(separator.source, flags + 'g');
-            string += ''; // Type-convert
             if (!compliantExecNpcg) {
                 // Doesn't need flags gy, but they don't hurt
                 separator2 = new RegExp('^' + separatorCopy.source + '$(?!\\s)', flags);
@@ -1478,7 +1600,7 @@ if (
                 // `separatorCopy.lastIndex` is not reliable cross-browser
                 lastIndex = match.index + match[0].length;
                 if (lastIndex > lastLastIndex) {
-                    array_push.call(output, strSlice(string, lastLastIndex, match.index));
+                    push(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) {
@@ -1493,7 +1615,7 @@ if (
                         /* eslint-enable no-loop-func */
                     }
                     if (match.length > 1 && match.index < string.length) {
-                        array_push.apply(output, array_slice.call(match, 1));
+                        array_push.apply(output, arraySlice(match, 1));
                     }
                     lastLength = match[0].length;
                     lastLastIndex = lastIndex;
@@ -1508,10 +1630,10 @@ if (
             }
             if (lastLastIndex === string.length) {
                 if (lastLength || !separatorCopy.test('')) {
-                    array_push.call(output, '');
+                    push(output, '');
                 }
             } else {
-                array_push.call(output, strSlice(string, lastLastIndex));
+                push(output, strSlice(string, lastLastIndex));
             }
             return output.length > splitLimit ? strSlice(output, 0, splitLimit) : output;
         };
@@ -1534,7 +1656,7 @@ var str_replace = StringPrototype.replace;
 var replaceReportsGroupsCorrectly = (function () {
     var groups = [];
     'x'.replace(/x(.)?/g, function (match, group) {
-        array_push.call(groups, group);
+        push(groups, group);
     });
     return groups.length === 1 && typeof groups[0] === 'undefined';
 }());
@@ -1552,7 +1674,7 @@ if (!replaceReportsGroupsCorrectly) {
                 searchValue.lastIndex = 0;
                 var args = searchValue.exec(match) || [];
                 searchValue.lastIndex = originalLastIndex;
-                array_push.call(args, arguments[length - 2], arguments[length - 1]);
+                push(args, arguments[length - 2], arguments[length - 1]);
                 return replaceValue.apply(this, args);
             };
             return str_replace.call(this, searchValue, wrappedReplaceValue);
@@ -1598,7 +1720,7 @@ defineProperties(StringPrototype, {
     }
 }, hasTrimWhitespaceBug);
 
-var hasLastIndexBug = String.prototype.lastIndexOf && 'abcあい'.lastIndexOf('あい', 2) !== -1;
+var hasLastIndexBug = StringPrototype.lastIndexOf && 'abcあい'.lastIndexOf('あい', 2) !== -1;
 defineProperties(StringPrototype, {
     lastIndexOf: function lastIndexOf(searchString) {
         if (typeof this === 'undefined' || this === null) {
@@ -1622,11 +1744,20 @@ defineProperties(StringPrototype, {
     }
 }, hasLastIndexBug);
 
+var originalLastIndexOf = StringPrototype.lastIndexOf;
+defineProperties(StringPrototype, {
+    lastIndexOf: function lastIndexOf(searchString) {
+        return originalLastIndexOf.apply(this, arguments);
+    }
+}, StringPrototype.lastIndexOf.length !== 1);
+
 // ES-5 15.1.2.2
+/* eslint-disable radix */
 if (parseInt(ws + '08') !== 8 || parseInt(ws + '0x16') !== 22) {
+/* eslint-enable radix */
     /* global parseInt: true */
     parseInt = (function (origParseInt) {
-        var hexRegex = /^0[xX]/;
+        var hexRegex = /^[\-+]?0[xX]/;
         return function parseInt(str, radix) {
             var string = $String(str).trim();
             var defaultedRadix = $Number(radix) || (hexRegex.test(string) ? 16 : 10);
@@ -1635,4 +1766,66 @@ if (parseInt(ws + '08') !== 8 || parseInt(ws + '0x16') !== 22) {
     }(parseInt));
 }
 
+if (String(new RangeError('test')) !== 'RangeError: test') {
+    var errorToStringShim = function toString() {
+        if (typeof this === 'undefined' || this === null) {
+            throw new TypeError("can't convert " + this + ' to object');
+        }
+        var name = this.name;
+        if (typeof name === 'undefined') {
+            name = 'Error';
+        } else if (typeof name !== 'string') {
+            name = $String(name);
+        }
+        var msg = this.message;
+        if (typeof msg === 'undefined') {
+            msg = '';
+        } else if (typeof msg !== 'string') {
+            msg = $String(msg);
+        }
+        if (!name) {
+            return msg;
+        }
+        if (!msg) {
+            return name;
+        }
+        return name + ': ' + msg;
+    };
+    // can't use defineProperties here because of toString enumeration issue in IE <= 8
+    Error.prototype.toString = errorToStringShim;
+}
+
+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);
+        }
+    };
+    ensureNonEnumerable(Error.prototype, 'message');
+    if (Error.prototype.message !== '') {
+      Error.prototype.message = '';
+    }
+    ensureNonEnumerable(Error.prototype, 'name');
+}
+
+if (String(/a/mig) !== '/a/gim') {
+    var regexToString = function toString() {
+        var str = '/' + this.source + '/';
+        if (this.global) {
+            str += 'g';
+        }
+        if (this.ignoreCase) {
+            str += 'i';
+        }
+        if (this.multiline) {
+            str += 'm';
+        }
+        return str;
+    };
+    // can't use defineProperties here because of toString enumeration issue in IE <= 8
+    RegExp.prototype.toString = regexToString;
+}
+
 }));
diff --git a/es5-shim.map b/es5-shim.map
index d5aeacc..a45d038 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","max","Math","min","to_string","toString","hasToStringTag", [...]
\ 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","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
diff --git a/es5-shim.min.js b/es5-shim.min.js
index 7a73022..5b43dbe 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.2.0/LICENSE
+ * see https://github.com/es-shims/es5-shim/blob/v4.4.1/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=Array;var t=e.prototype;var r=Object;var n=r.prototype;var a=Function.prototype;var i=String;var o=i.prototype;var l=Number;var u=l.prototype;var f=t.slice;var s=t.splice;var c=t.push;var v=t.unshift;var p=t.concat;var h=a.call;var g=Math.max;var y=Math.min;var d=n.toString;var w=typeof Symbol==="function" [...]
+(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 [...]
 //# sourceMappingURL=es5-shim.map
diff --git a/package.json b/package.json
index fa958fa..611bbf0 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "es5-shim",
-  "version": "4.2.0",
+  "version": "4.4.1",
   "description": "ECMAScript 5 compatibility shims for legacy JavaScript engines",
   "homepage": "http://github.com/es-shims/es5-shim/",
   "contributors": [
@@ -25,20 +25,21 @@
     "minify": "npm run minify-shim && npm run 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 && jasmine-node --matchall ./ tests/spec/",
+    "test": "npm run lint && npm run tests-only",
+    "tests-only": "jasmine-node --matchall ./ tests/spec/",
     "test-native": "jasmine-node --matchall tests/spec/",
     "lint": "npm run jscs && npm run 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.7.3",
-    "@ljharb/eslint-config": "^1.4.1",
+    "eslint": "^1.10.1",
+    "@ljharb/eslint-config": "^1.6.0",
     "jasmine-node": "^1.14.5",
-    "jscs": "^2.4.0",
-    "uglify-js": "^2.5.0",
+    "jscs": "^2.6.0",
+    "uglify-js": "^2.6.1",
     "replace": "^0.3.0",
-    "semver": "^5.0.3"
+    "semver": "^5.1.0"
   },
   "engines": {
     "node": ">=0.4.0"
diff --git a/tests/index.html b/tests/index.html
index a797edd..f09492d 100644
--- a/tests/index.html
+++ b/tests/index.html
@@ -1,6 +1,7 @@
 <!DOCTYPE HTML>
 <html>
 <head>
+	<meta charset="utf-8" />
 	<title>Jasmine Spec Runner</title>
 
 	<link rel="shortcut icon" type="image/png" href="lib/jasmine_favicon.png">
@@ -19,11 +20,14 @@
 
 	<!-- include spec files here... -->
 	<script src="spec/s-array.js"></script>
+	<script src="spec/s-date.js"></script>
+	<script src="spec/s-error.js"></script>
 	<script src="spec/s-function.js"></script>
-	<script src="spec/s-string.js"></script>
-	<script src="spec/s-object.js"></script>
+	<script src="spec/s-global.js"></script>
 	<script src="spec/s-number.js"></script>
-	<script src="spec/s-date.js"></script>
+	<script src="spec/s-object.js"></script>
+	<script src="spec/s-string.js"></script>
+	<script src="spec/s-regexp.js"></script>
 
 
 	<script type="text/javascript">
diff --git a/tests/index.min.html b/tests/index.min.html
index b8ac467..5a265ca 100644
--- a/tests/index.min.html
+++ b/tests/index.min.html
@@ -18,11 +18,13 @@
 
 	<!-- include spec files here... -->
 	<script src="spec/s-array.js"></script>
+	<script src="spec/s-date.js"></script>
+	<script src="spec/s-error.js"></script>
 	<script src="spec/s-function.js"></script>
-	<script src="spec/s-string.js"></script>
-	<script src="spec/s-object.js"></script>
+	<script src="spec/s-global.js"></script>
 	<script src="spec/s-number.js"></script>
-	<script src="spec/s-date.js"></script>
+	<script src="spec/s-object.js"></script>
+	<script src="spec/s-string.js"></script>
 
 
 	<script type="text/javascript">
diff --git a/tests/native.html b/tests/native.html
index 82631ff..37811fa 100644
--- a/tests/native.html
+++ b/tests/native.html
@@ -1,6 +1,7 @@
 <!DOCTYPE HTML>
 <html>
 <head>
+	<meta charset="utf-8" />
 	<title>Jasmine Spec Runner</title>
 
 	<link rel="shortcut icon" type="image/png" href="lib/jasmine_favicon.png">
@@ -15,11 +16,14 @@
 
 	<!-- include spec files here... -->
 	<script src="spec/s-array.js"></script>
+	<script src="spec/s-date.js"></script>
+	<script src="spec/s-error.js"></script>
 	<script src="spec/s-function.js"></script>
-	<script src="spec/s-string.js"></script>
-	<script src="spec/s-object.js"></script>
+	<script src="spec/s-global.js"></script>
 	<script src="spec/s-number.js"></script>
-	<script src="spec/s-date.js"></script>
+	<script src="spec/s-object.js"></script>
+	<script src="spec/s-string.js"></script>
+	<script src="spec/s-regexp.js"></script>
 
 
 	<script type="text/javascript">
diff --git a/tests/spec/s-array.js b/tests/spec/s-array.js
index 4de5872..734f7aa 100644
--- a/tests/spec/s-array.js
+++ b/tests/spec/s-array.js
@@ -1,19 +1,24 @@
 /* global describe, it, expect, beforeEach, jasmine, xit */
 
 var toStr = Object.prototype.toString;
-// var canDistinguishSparseFromUndefined = 0 in [undefined]; // IE 6 - 8 have a bug where this returns false.
+var canDistinguishSparseFromUndefined = 0 in [undefined]; // IE 6 - 8 have a bug where this returns false.
+var ifHasDenseUndefinedsIt = canDistinguishSparseFromUndefined ? it : xit;
+var undefinedIfNoSparseBug = canDistinguishSparseFromUndefined ? undefined : { valueOf: function () { return 0; } };
 var hasStrictMode = (function () {
   'use strict';
 
    return !this;
 }());
+var ifHasStrictIt = hasStrictMode ? it : xit;
 
 describe('Array', function () {
     var testSubject;
+
     beforeEach(function () {
-        testSubject = [2, 3, undefined, true, 'hej', null, false, 0];
+        testSubject = [2, 3, undefinedIfNoSparseBug, true, 'hej', null, false, 0];
         delete testSubject[1];
     });
+
     var createArrayLikeFromArray = function createArrayLikeFromArray(arr) {
         var o = {};
         Array.prototype.forEach.call(arr, function (e, i) {
@@ -23,24 +28,26 @@ describe('Array', function () {
         return o;
     };
 
-    describe('forEach', function () {
+    describe('#forEach()', function () {
         var expected, actual;
 
         beforeEach(function () {
-            expected = { 0: 2, 2: undefined, 3: true, 4: 'hej', 5: null, 6: false, 7: 0 };
+            expected = { 0: 2, 2: undefinedIfNoSparseBug, 3: true, 4: 'hej', 5: null, 6: false, 7: 0 };
             actual = {};
         });
+
         it('should pass the right parameters', function () {
-            var callback = jasmine.createSpy('callback'),
-                array = ['1'];
+            var callback = jasmine.createSpy('callback');
+            var array = ['1'];
             array.forEach(callback);
             expect(callback).toHaveBeenCalledWith('1', 0, array);
         });
+
         it('should not affect elements added to the array after it has begun', function () {
-            var arr = [1, 2, 3],
-                i = 0;
+            var arr = [1, 2, 3];
+            var i = 0;
             arr.forEach(function (a) {
-                i++;
+                i += 1;
                 arr.push(a + 3);
             });
             expect(arr).toEqual([1, 2, 3, 4, 5, 6]);
@@ -52,12 +59,14 @@ describe('Array', function () {
             [1].forEach(function () { context = this; });
             expect(context).toBe(function () { return this; }.call());
         });
+
         it('should iterate all', function () {
             testSubject.forEach(function (obj, index) {
                 actual[index] = obj;
             });
             expect(actual).toExactlyMatch(expected);
         });
+
         it('should iterate all using a context', function () {
             var o = { a: actual };
 
@@ -74,9 +83,10 @@ describe('Array', function () {
             });
             expect(actual).toExactlyMatch(expected);
         });
+
         it('should iterate all in an array-like object using a context', function () {
-            var ts = createArrayLikeFromArray(testSubject),
-                o = { a: actual };
+            var ts = createArrayLikeFromArray(testSubject);
+            var o = { a: actual };
 
             Array.prototype.forEach.call(ts, function (obj, index) {
                 this.a[index] = obj;
@@ -86,6 +96,7 @@ describe('Array', function () {
 
         describe('strings', function () {
             var str = 'Hello, World!';
+
             it('should iterate all in a string', function () {
                 actual = [];
                 Array.prototype.forEach.call(str, function (item, index) {
@@ -93,6 +104,7 @@ describe('Array', function () {
                 });
                 expect(actual).toExactlyMatch(str.split(''));
             });
+
             it('should iterate all in a string using a context', function () {
                 actual = [];
                 var o = { a: actual };
@@ -102,6 +114,7 @@ describe('Array', function () {
                 expect(actual).toExactlyMatch(str.split(''));
             });
         });
+
         it('should have a boxed object as list argument of callback', function () {
             var listArg;
             Array.prototype.forEach.call('foo', function (item, index, list) {
@@ -110,23 +123,22 @@ describe('Array', function () {
             expect(typeof listArg).toBe('object');
             expect(toStr.call(listArg)).toBe('[object String]');
         });
-        if (hasStrictMode) {
-            it('does not autobox the content in strict mode', function () {
-                var context;
-                [1].forEach(function () {
-                    'use strict';
 
-                    context = this;
-                }, 'x');
-                expect(typeof context).toBe('string');
-            });
-        }
+        ifHasStrictIt('does not autobox the content in strict mode', function () {
+            var context;
+            [1].forEach(function () {
+                'use strict';
+
+                context = this;
+            }, 'x');
+            expect(typeof context).toBe('string');
+        });
     });
-    describe('some', function () {
+    describe('#some()', function () {
         var actual, expected, numberOfRuns;
 
         beforeEach(function () {
-            expected = { 0: 2, 2: undefined, 3: true };
+            expected = { 0: 2, 2: undefinedIfNoSparseBug, 3: true };
             actual = {};
             numberOfRuns = 0;
         });
@@ -137,17 +149,19 @@ describe('Array', function () {
             array.some(callback);
             expect(callback).toHaveBeenCalledWith('1', 0, array);
         });
+
         it('should not affect elements added to the array after it has begun', function () {
-            var arr = [1, 2, 3],
-                i = 0;
+            var arr = [1, 2, 3];
+            var i = 0;
             arr.some(function (a) {
-                i++;
+                i += 1;
                 arr.push(a + 3);
                 return i > 3;
             });
             expect(arr).toEqual([1, 2, 3, 4, 5, 6]);
             expect(i).toBe(3);
         });
+
         it('should set the right context when given none', function () {
             var context;
             [1].some(function () { context = this; });
@@ -158,10 +172,12 @@ describe('Array', function () {
             actual = testSubject.some(function () {});
             expect(actual).toBeFalsy();
         });
+
         it('should return true if it is stopped somewhere', function () {
             actual = testSubject.some(function () { return true; });
             expect(actual).toBeTruthy();
         });
+
         it('should return false if there are no elements', function () {
             actual = [].some(function () { return true; });
             expect(actual).toBeFalsy();
@@ -175,6 +191,7 @@ describe('Array', function () {
             });
             expect(actual).toExactlyMatch(expected);
         });
+
         it('should stop after 3 elements using a context', function () {
             var o = { a: actual };
             testSubject.some(function (obj, index) {
@@ -194,6 +211,7 @@ describe('Array', function () {
             });
             expect(actual).toExactlyMatch(expected);
         });
+
         it('should stop after 3 elements in an array-like object using a context', function () {
             var ts = createArrayLikeFromArray(testSubject);
             var o = { a: actual };
@@ -204,6 +222,7 @@ describe('Array', function () {
             }, o);
             expect(actual).toExactlyMatch(expected);
         });
+
         it('should have a boxed object as list argument of callback', function () {
             var listArg;
             Array.prototype.some.call('foo', function (item, index, list) {
@@ -213,11 +232,11 @@ describe('Array', function () {
             expect(toStr.call(listArg)).toBe('[object String]');
         });
     });
-    describe('every', function () {
+    describe('#every()', function () {
         var actual, expected, numberOfRuns;
 
         beforeEach(function () {
-            expected = { 0: 2, 2: undefined, 3: true };
+            expected = { 0: 2, 2: undefinedIfNoSparseBug, 3: true };
             actual = {};
             numberOfRuns = 0;
         });
@@ -228,17 +247,19 @@ describe('Array', function () {
             array.every(callback);
             expect(callback).toHaveBeenCalledWith('1', 0, array);
         });
+
         it('should not affect elements added to the array after it has begun', function () {
-            var arr = [1, 2, 3],
-                i = 0;
+            var arr = [1, 2, 3];
+            var i = 0;
             arr.every(function (a) {
-                i++;
+                i += 1;
                 arr.push(a + 3);
                 return i <= 3;
             });
             expect(arr).toEqual([1, 2, 3, 4, 5, 6]);
             expect(i).toBe(3);
         });
+
         it('should set the right context when given none', function () {
             var context;
             [1].every(function () { context = this; });
@@ -252,10 +273,12 @@ describe('Array', function () {
             actual = [].every(function () { return false; });
             expect(actual).toBeTruthy();
         });
+
         it('should return true if it runs to the end', function () {
             actual = [1, 2, 3].every(function () { return true; });
             expect(actual).toBeTruthy();
         });
+
         it('should return false if it is stopped before the end', function () {
             actual = [1, 2, 3].every(function () { return false; });
             expect(actual).toBeFalsy();
@@ -269,6 +292,7 @@ describe('Array', function () {
             });
             expect(actual).toExactlyMatch(expected);
         });
+
         it('should stop after 3 elements using a context', function () {
             var o = { a: actual };
             testSubject.every(function (obj, index) {
@@ -288,6 +312,7 @@ describe('Array', function () {
             });
             expect(actual).toExactlyMatch(expected);
         });
+
         it('should stop after 3 elements in an array-like object using a context', function () {
             var ts = createArrayLikeFromArray(testSubject);
             var o = { a: actual };
@@ -298,6 +323,7 @@ describe('Array', function () {
             }, o);
             expect(actual).toExactlyMatch(expected);
         });
+
         it('should have a boxed object as list argument of callback', function () {
             var listArg;
             Array.prototype.every.call('foo', function (item, index, list) {
@@ -308,15 +334,14 @@ describe('Array', function () {
         });
     });
 
-    describe('indexOf', function () {
+    describe('#indexOf()', function () {
         'use strict';
 
         var actual, expected;
 
         beforeEach(function () {
-            testSubject = [2, 3, undefined, true, 'hej', null, 2, false, 0];
+            testSubject = [2, 3, undefinedIfNoSparseBug, true, 'hej', null, 2, false, 0];
             delete testSubject[1];
-
         });
 
         it('should find the element', function () {
@@ -324,21 +349,25 @@ describe('Array', function () {
             actual = testSubject.indexOf('hej');
             expect(actual).toBe(expected);
         });
+
         it('should not find the element', function () {
             expected = -1;
             actual = testSubject.indexOf('mus');
             expect(actual).toBe(expected);
         });
-        it('should find undefined as well', function () {
+
+        ifHasDenseUndefinedsIt('should find undefined as well', function () {
             expected = -1;
             actual = testSubject.indexOf(undefined);
             expect(actual).not.toBe(expected);
         });
-        it('should skip unset indexes', function () {
+
+        ifHasDenseUndefinedsIt('should skip unset indexes', function () {
             expected = 2;
             actual = testSubject.indexOf(undefined);
             expect(actual).toBe(expected);
         });
+
         it('should use a strict test', function () {
             actual = testSubject.indexOf(null);
             expect(actual).toBe(5);
@@ -346,53 +375,63 @@ describe('Array', function () {
             actual = testSubject.indexOf('2');
             expect(actual).toBe(-1);
         });
+
         it('should skip the first if fromIndex is set', function () {
             expect(testSubject.indexOf(2, 2)).toBe(6);
             expect(testSubject.indexOf(2, 0)).toBe(0);
             expect(testSubject.indexOf(2, 6)).toBe(6);
         });
+
         it('should work with negative fromIndex', function () {
             expect(testSubject.indexOf(2, -3)).toBe(6);
             expect(testSubject.indexOf(2, -9)).toBe(0);
         });
+
         it('should work with fromIndex being greater than the length', function () {
             expect(testSubject.indexOf(0, 20)).toBe(-1);
         });
+
         it('should work with fromIndex being negative and greater than the length', function () {
             expect(testSubject.indexOf('hej', -20)).toBe(4);
         });
 
         describe('Array-like', function ArrayLike() {
-            var indexOf = Array.prototype.indexOf,
-                testAL;
+            var indexOf = Array.prototype.indexOf;
+            var testAL;
+
             beforeEach(function beforeEach() {
                 testAL = {};
-                testSubject = [2, 3, undefined, true, 'hej', null, 2, false, 0];
+                testSubject = [2, 3, undefinedIfNoSparseBug, true, 'hej', null, 2, false, 0];
                 testSubject.forEach(function (o, i) {
                     testAL[i] = o;
                 });
                 testAL.length = testSubject.length;
             });
+
             it('should find the element (array-like)', function () {
                 expected = 4;
                 actual = indexOf.call(testAL, 'hej');
                 expect(actual).toBe(expected);
             });
+
             it('should not find the element (array-like)', function () {
                 expected = -1;
                 actual = indexOf.call(testAL, 'mus');
                 expect(actual).toBe(expected);
             });
-            it('should find undefined as well (array-like)', function () {
+
+            ifHasDenseUndefinedsIt('should find undefined as well (array-like)', function () {
                 expected = -1;
                 actual = indexOf.call(testAL, undefined);
                 expect(actual).not.toBe(expected);
             });
-            it('should skip unset indexes (array-like)', function () {
+
+            ifHasDenseUndefinedsIt('should skip unset indexes (array-like)', function () {
                 expected = 2;
                 actual = indexOf.call(testAL, undefined);
                 expect(actual).toBe(expected);
             });
+
             it('should use a strict test (array-like)', function () {
                 actual = Array.prototype.indexOf.call(testAL, null);
                 expect(actual).toBe(5);
@@ -400,54 +439,63 @@ describe('Array', function () {
                 actual = Array.prototype.indexOf.call(testAL, '2');
                 expect(actual).toBe(-1);
             });
+
             it('should skip the first if fromIndex is set (array-like)', function () {
                 expect(indexOf.call(testAL, 2, 2)).toBe(6);
                 expect(indexOf.call(testAL, 2, 0)).toBe(0);
                 expect(indexOf.call(testAL, 2, 6)).toBe(6);
             });
+
             it('should work with negative fromIndex (array-like)', function () {
                 expect(indexOf.call(testAL, 2, -3)).toBe(6);
                 expect(indexOf.call(testAL, 2, -9)).toBe(0);
             });
+
             it('should work with fromIndex being greater than the length (array-like)', function () {
                 expect(indexOf.call(testAL, 0, 20)).toBe(-1);
             });
+
             it('should work with fromIndex being negative and greater than the length (array-like)', function () {
                 expect(indexOf.call(testAL, 'hej', -20)).toBe(4);
             });
         });
     });
-    describe('lastIndexOf', function () {
+    describe('#lastIndexOf()', function () {
         'use strict';
 
         var actual, expected;
 
         beforeEach(function () {
-            testSubject = [2, 3, undefined, true, 'hej', null, 2, 3, false, 0];
+            testSubject = [2, 3, undefinedIfNoSparseBug, true, 'hej', null, 2, 3, false, 0];
             delete testSubject[1];
             delete testSubject[7];
         });
+
         describe('Array', function () {
             it('should find the element', function () {
                 expected = 4;
                 actual = testSubject.lastIndexOf('hej');
                 expect(actual).toBe(expected);
             });
+
             it('should not find the element', function () {
                 expected = -1;
                 actual = testSubject.lastIndexOf('mus');
                 expect(actual).toBe(expected);
             });
-            it('should find undefined as well', function () {
+
+            ifHasDenseUndefinedsIt('should find undefined as well', function () {
                 expected = -1;
                 actual = testSubject.lastIndexOf(undefined);
                 expect(actual).not.toBe(expected);
             });
-            it('should skip unset indexes', function () {
+
+            ifHasDenseUndefinedsIt('should skip unset indexes', function () {
                 expected = 2;
                 actual = testSubject.lastIndexOf(undefined);
                 expect(actual).toBe(expected);
             });
+
             it('should use a strict test', function () {
                 actual = testSubject.lastIndexOf(null);
                 expect(actual).toBe(5);
@@ -455,26 +503,31 @@ describe('Array', function () {
                 actual = testSubject.lastIndexOf('2');
                 expect(actual).toBe(-1);
             });
+
             it('should skip the first if fromIndex is set', function () {
                 expect(testSubject.lastIndexOf(2, 2)).toBe(0);
                 expect(testSubject.lastIndexOf(2, 0)).toBe(0);
                 expect(testSubject.lastIndexOf(2, 6)).toBe(6);
             });
+
             it('should work with negative fromIndex', function () {
                 expect(testSubject.lastIndexOf(2, -3)).toBe(6);
                 expect(testSubject.lastIndexOf(2, -9)).toBe(0);
             });
+
             it('should work with fromIndex being greater than the length', function () {
                 expect(testSubject.lastIndexOf(2, 20)).toBe(6);
             });
+
             it('should work with fromIndex being negative and greater than the length', function () {
                 expect(testSubject.lastIndexOf(2, -20)).toBe(-1);
             });
         });
 
         describe('Array like', function () {
-            var lastIndexOf = Array.prototype.lastIndexOf,
-                testAL;
+            var lastIndexOf = Array.prototype.lastIndexOf;
+            var testAL;
+
             beforeEach(function () {
                 testAL = {};
                 testSubject.forEach(function (o, i) {
@@ -482,26 +535,31 @@ describe('Array', function () {
                 });
                 testAL.length = testSubject.length;
             });
+
             it('should find the element (array-like)', function () {
                 expected = 4;
                 actual = lastIndexOf.call(testAL, 'hej');
                 expect(actual).toBe(expected);
             });
+
             it('should not find the element (array-like)', function () {
                 expected = -1;
                 actual = lastIndexOf.call(testAL, 'mus');
                 expect(actual).toBe(expected);
             });
-            it('should find undefined as well (array-like)', function () {
+
+            ifHasDenseUndefinedsIt('should find undefined as well (array-like)', function () {
                 expected = -1;
                 actual = lastIndexOf.call(testAL, undefined);
                 expect(actual).not.toBe(expected);
             });
-            it('should skip unset indexes (array-like)', function () {
+
+            ifHasDenseUndefinedsIt('should skip unset indexes (array-like)', function () {
                 expected = 2;
                 actual = lastIndexOf.call(testAL, undefined);
                 expect(actual).toBe(expected);
             });
+
             it('should use a strict test (array-like)', function () {
                 actual = lastIndexOf.call(testAL, null);
                 expect(actual).toBe(5);
@@ -509,48 +567,52 @@ describe('Array', function () {
                 actual = lastIndexOf.call(testAL, '2');
                 expect(actual).toBe(-1);
             });
+
             it('should skip the first if fromIndex is set', function () {
                 expect(lastIndexOf.call(testAL, 2, 2)).toBe(0);
                 expect(lastIndexOf.call(testAL, 2, 0)).toBe(0);
                 expect(lastIndexOf.call(testAL, 2, 6)).toBe(6);
             });
+
             it('should work with negative fromIndex', function () {
                 expect(lastIndexOf.call(testAL, 2, -3)).toBe(6);
                 expect(lastIndexOf.call(testAL, 2, -9)).toBe(0);
             });
+
             it('should work with fromIndex being greater than the length', function () {
                 expect(lastIndexOf.call(testAL, 2, 20)).toBe(6);
             });
+
             it('should work with fromIndex being negative and greater than the length', function () {
                 expect(lastIndexOf.call(testAL, 2, -20)).toBe(-1);
             });
         });
     });
 
-    describe('filter', function () {
-        var filteredArray,
-            callback = function callback(o, i) {
-                return i !== 3 && i !== 5;
-            };
+    describe('#filter()', function () {
+        var filteredArray;
+        var callback = function callback(o, i) {
+            return i !== 3 && i !== 5;
+        };
 
         beforeEach(function () {
-            testSubject = [2, 3, undefined, true, 'hej', 3, null, false, 0];
+            testSubject = [2, 3, undefinedIfNoSparseBug, true, 'hej', 3, null, false, 0];
             delete testSubject[1];
-            filteredArray = [2, undefined, 'hej', null, false, 0];
+            filteredArray = [2, undefinedIfNoSparseBug, 'hej', null, false, 0];
         });
         describe('Array object', function () {
-
             it('should call the callback with the proper arguments', function () {
                 var predicate = jasmine.createSpy('predicate');
                 var arr = ['1'];
                 arr.filter(predicate);
                 expect(predicate).toHaveBeenCalledWith('1', 0, arr);
             });
+
             it('should not affect elements added to the array after it has begun', function () {
                 var arr = [1, 2, 3];
                 var i = 0;
                 arr.filter(function (a) {
-                    i++;
+                    i += 1;
                     if (i <= 4) {
                         arr.push(a + 3);
                     }
@@ -559,7 +621,8 @@ describe('Array', function () {
                 expect(arr).toEqual([1, 2, 3, 4, 5, 6]);
                 expect(i).toBe(3);
             });
-            it('should skip non-set values', function () {
+
+            ifHasDenseUndefinedsIt('should skip unset values', function () {
                 var passedValues = {};
                 testSubject = [1, 2, 3, 4];
                 delete testSubject[1];
@@ -569,6 +632,7 @@ describe('Array', function () {
                 });
                 expect(passedValues).toExactlyMatch(testSubject);
             });
+
             it('should pass the right context to the filter', function () {
                 var passedValues = {};
                 testSubject = [1, 2, 3, 4];
@@ -579,20 +643,24 @@ describe('Array', function () {
                 }, passedValues);
                 expect(passedValues).toExactlyMatch(testSubject);
             });
+
             it('should set the right context when given none', function () {
                 var context;
                 [1].filter(function () { context = this; });
                 expect(context).toBe(function () { return this; }.call());
             });
+
             it('should remove only the values for which the callback returns false', function () {
                 var result = testSubject.filter(callback);
                 expect(result).toExactlyMatch(filteredArray);
             });
+
             it('should leave the original array untouched', function () {
                 var copy = testSubject.slice();
                 testSubject.filter(callback);
                 expect(testSubject).toExactlyMatch(copy);
             });
+
             it('should not be affected by same-index mutation', function () {
                 var results = [1, 2, 3].filter(function (value, index, array) {
                     array[index] = 'a';
@@ -601,30 +669,34 @@ describe('Array', function () {
                 expect(results).toEqual([1, 2, 3]);
             });
         });
+
         describe('Array like', function () {
             beforeEach(function () {
                 testSubject = createArrayLikeFromArray(testSubject);
             });
+
             it('should call the predicate with the proper arguments', function () {
                 var predicate = jasmine.createSpy('predicate');
                 var arr = createArrayLikeFromArray(['1']);
                 Array.prototype.filter.call(arr, predicate);
                 expect(predicate).toHaveBeenCalledWith('1', 0, arr);
             });
+
             it('should not affect elements added to the array after it has begun', function () {
-                var arr = createArrayLikeFromArray([1, 2, 3]),
-                    i = 0;
+                var arr = createArrayLikeFromArray([1, 2, 3]);
+                var i = 0;
                 Array.prototype.filter.call(arr, function (a) {
-                    i++;
+                    i += 1;
                     if (i <= 4) {
                         arr[i + 2] = a + 3;
                         arr.length += 1;
                     }
                     return true;
                 });
-                expect(arr).toEqual([1, 2, 3, 4, 5, 6]);
+                expect(Array.prototype.slice.call(arr)).toEqual([1, 2, 3, 4, 5, 6]);
                 expect(i).toBe(3);
             });
+
             it('should skip non-set values', function () {
                 var passedValues = createArrayLikeFromArray([]);
                 testSubject = createArrayLikeFromArray([1, 2, 3, 4]);
@@ -636,11 +708,13 @@ describe('Array', function () {
                 });
                 expect(passedValues).toEqual(testSubject);
             });
+
             it('should set the right context when given none', function () {
                 var context;
                 Array.prototype.filter.call(createArrayLikeFromArray([1]), function () { context = this; }, undefined);
                 expect(context).toBe(function () { return this; }.call());
             });
+
             it('should pass the right context to the filter', function () {
                 var passedValues = {};
                 testSubject = createArrayLikeFromArray([1, 2, 3, 4]);
@@ -652,16 +726,19 @@ describe('Array', function () {
                 }, passedValues);
                 expect(passedValues).toEqual(testSubject);
             });
+
             it('should remove only the values for which the callback returns false', function () {
                 var result = Array.prototype.filter.call(testSubject, callback);
                 expect(result).toExactlyMatch(filteredArray);
             });
+
             it('should leave the original array untouched', function () {
                 var copy = createArrayLikeFromArray(testSubject);
                 Array.prototype.filter.call(testSubject, callback);
                 expect(testSubject).toExactlyMatch(copy);
             });
         });
+
         it('should have a boxed object as list argument of callback', function () {
             var actual;
             Array.prototype.filter.call('foo', function (item, index, list) {
@@ -671,7 +748,7 @@ describe('Array', function () {
             expect(toStr.call(actual)).toBe('[object String]');
         });
     });
-    describe('map', function () {
+    describe('#map()', function () {
         var callback;
         beforeEach(function () {
             var i = 0;
@@ -686,6 +763,7 @@ describe('Array', function () {
                 array.map(mapper);
                 expect(mapper).toHaveBeenCalledWith(1, 0, array);
             });
+
             it('should set the context correctly', function () {
                 var context = {};
                 testSubject.map(function (o, i) {
@@ -693,39 +771,44 @@ describe('Array', function () {
                 }, context);
                 expect(context).toExactlyMatch(testSubject);
             });
+
             it('should set the right context when given none', function () {
                 var context;
                 [1].map(function () { context = this; });
                 expect(context).toBe(function () { return this; }.call());
             });
+
             it('should not change the array it is called on', function () {
                 var copy = testSubject.slice();
                 testSubject.map(callback);
                 expect(testSubject).toExactlyMatch(copy);
             });
+
             it('should only run for the number of objects in the array when it started', function () {
-                var arr = [1, 2, 3],
-                    i = 0;
+                var arr = [1, 2, 3];
+                var i = 0;
                 arr.map(function (o) {
                     arr.push(o + 3);
-                    i++;
+                    i += 1;
                     return o;
                 });
                 expect(arr).toExactlyMatch([1, 2, 3, 4, 5, 6]);
                 expect(i).toBe(3);
             });
+
             it('should properly translate the values as according to the callback', function () {
-                var result = testSubject.map(callback),
-                    expected = [0, 0, 1, 2, 3, 4, 5, 6];
+                var result = testSubject.map(callback);
+                var expected = [0, 0, 1, 2, 3, 4, 5, 6];
                 delete expected[1];
                 expect(result).toExactlyMatch(expected);
             });
+
             it('should skip non-existing values', function () {
-                var array = [1, 2, 3, 4],
-                    i = 0;
+                var array = [1, 2, 3, 4];
+                var i = 0;
                 delete array[2];
                 array.map(function () {
-                    i++;
+                    i += 1;
                 });
                 expect(i).toBe(3);
             });
@@ -734,12 +817,14 @@ describe('Array', function () {
             beforeEach(function () {
                 testSubject = createArrayLikeFromArray(testSubject);
             });
+
             it('should call mapper with the right parameters', function () {
                 var mapper = jasmine.createSpy('mapper');
                 var array = createArrayLikeFromArray([1]);
                 Array.prototype.map.call(array, mapper);
                 expect(mapper).toHaveBeenCalledWith(1, 0, array);
             });
+
             it('should set the context correctly', function () {
                 var context = {};
                 Array.prototype.map.call(testSubject, function (o, i) {
@@ -748,43 +833,49 @@ describe('Array', function () {
                 }, context);
                 expect(context).toEqual(testSubject);
             });
+
             it('should set the right context when given none', function () {
                 var context;
                 Array.prototype.map.call(createArrayLikeFromArray([1]), function () { context = this; });
                 expect(context).toBe(function () { return this; }.call());
             });
+
             it('should not change the array it is called on', function () {
                 var copy = createArrayLikeFromArray(testSubject);
                 Array.prototype.map.call(testSubject, callback);
                 expect(testSubject).toExactlyMatch(copy);
             });
+
             it('should only run for the number of objects in the array when it started', function () {
-                var arr = createArrayLikeFromArray([1, 2, 3]),
-                    i = 0;
+                var arr = createArrayLikeFromArray([1, 2, 3]);
+                var i = 0;
                 Array.prototype.map.call(arr, function (o) {
                     Array.prototype.push.call(arr, o + 3);
-                    i++;
+                    i += 1;
                     return o;
                 });
-                expect(arr).toEqual([1, 2, 3, 4, 5, 6]);
+                expect(Array.prototype.slice.call(arr)).toEqual([1, 2, 3, 4, 5, 6]);
                 expect(i).toBe(3);
             });
+
             it('should properly translate the values as according to the callback', function () {
-                var result = Array.prototype.map.call(testSubject, callback),
-                    expected = [0, 0, 1, 2, 3, 4, 5, 6];
+                var result = Array.prototype.map.call(testSubject, callback);
+                var expected = [0, 0, 1, 2, 3, 4, 5, 6];
                 delete expected[1];
                 expect(result).toExactlyMatch(expected);
             });
+
             it('should skip non-existing values', function () {
-                var array = createArrayLikeFromArray([1, 2, 3, 4]),
-                    i = 0;
+                var array = createArrayLikeFromArray([1, 2, 3, 4]);
+                var i = 0;
                 delete array[2];
                 Array.prototype.map.call(array, function () {
-                    i++;
+                    i += 1;
                 });
                 expect(i).toBe(3);
             });
         });
+
         it('should have a boxed object as list argument of callback', function () {
             var actual;
             Array.prototype.map.call('foo', function (item, index, list) {
@@ -795,7 +886,7 @@ describe('Array', function () {
         });
     });
 
-    describe('reduce', function () {
+    describe('#reduce()', function () {
         beforeEach(function () {
             testSubject = [1, 2, 3];
         });
@@ -806,16 +897,18 @@ describe('Array', function () {
                 testSubject.reduce(spy);
                 expect(spy.calls[0].args).toExactlyMatch([1, 2, 1, testSubject]);
             });
+
             it('should start with the right initialValue', function () {
                 var spy = jasmine.createSpy().andReturn(0);
                 testSubject.reduce(spy, 0);
                 expect(spy.calls[0].args).toExactlyMatch([0, 1, 0, testSubject]);
             });
+
             it('should not affect elements added to the array after it has begun', function () {
-                var arr = [1, 2, 3],
-                    i = 0;
+                var arr = [1, 2, 3];
+                var i = 0;
                 arr.reduce(function (a, b) {
-                    i++;
+                    i += 1;
                     if (i <= 4) {
                         arr.push(a + 3);
                     }
@@ -824,6 +917,7 @@ describe('Array', function () {
                 expect(arr).toEqual([1, 2, 3, 4, 5]);
                 expect(i).toBe(2);
             });
+
             it('should work as expected for empty arrays', function () {
                 var spy = jasmine.createSpy();
                 expect(function () {
@@ -831,16 +925,19 @@ describe('Array', function () {
                 }).toThrow();
                 expect(spy).not.toHaveBeenCalled();
             });
+
             it('should throw correctly if no callback is given', function () {
                 expect(function () {
                     testSubject.reduce();
                 }).toThrow();
             });
+
             it('should return the expected result', function () {
                 expect(testSubject.reduce(function (a, b) {
                     return String(a || '') + String(b || '');
-                })).toEqual(testSubject.join(''));
+                })).toBe(testSubject.join(''));
             });
+
             it('should not directly affect the passed array', function () {
                 var copy = testSubject.slice();
                 testSubject.reduce(function (a, b) {
@@ -848,6 +945,7 @@ describe('Array', function () {
                 });
                 expect(testSubject).toEqual(copy);
             });
+
             it('should skip non-set values', function () {
                 delete testSubject[1];
                 var visited = {};
@@ -859,6 +957,7 @@ describe('Array', function () {
 
                 expect(visited).toEqual({ 1: true, 3: true });
             });
+
             it('should have the right length', function () {
                 expect(testSubject.reduce.length).toBe(1);
             });
@@ -868,21 +967,24 @@ describe('Array', function () {
                 testSubject = createArrayLikeFromArray(testSubject);
                 testSubject.reduce = Array.prototype.reduce;
             });
+
             it('should pass the correct arguments to the callback', function () {
                 var spy = jasmine.createSpy().andReturn(0);
                 testSubject.reduce(spy);
                 expect(spy.calls[0].args).toExactlyMatch([1, 2, 1, testSubject]);
             });
+
             it('should start with the right initialValue', function () {
                 var spy = jasmine.createSpy().andReturn(0);
                 testSubject.reduce(spy, 0);
                 expect(spy.calls[0].args).toExactlyMatch([0, 1, 0, testSubject]);
             });
+
             it('should not affect elements added to the array after it has begun', function () {
-                var arr = createArrayLikeFromArray([1, 2, 3]),
-                    i = 0;
+                var arr = createArrayLikeFromArray([1, 2, 3]);
+                var i = 0;
                 Array.prototype.reduce.call(arr, function (a, b) {
-                    i++;
+                    i += 1;
                     if (i <= 4) {
                         arr[i + 2] = a + 3;
                     }
@@ -898,6 +1000,7 @@ describe('Array', function () {
                 });
                 expect(i).toBe(2);
             });
+
             it('should work as expected for empty arrays', function () {
                 var spy = jasmine.createSpy();
                 expect(function () {
@@ -905,16 +1008,19 @@ describe('Array', function () {
                 }).toThrow();
                 expect(spy).not.toHaveBeenCalled();
             });
+
             it('should throw correctly if no callback is given', function () {
                 expect(function () {
                     testSubject.reduce();
                 }).toThrow();
             });
+
             it('should return the expected result', function () {
                 expect(testSubject.reduce(function (a, b) {
                     return String(a || '') + String(b || '');
-                })).toEqual('123');
+                })).toBe('123');
             });
+
             it('should not directly affect the passed array', function () {
                 var copy = createArrayLikeFromArray(testSubject);
                 testSubject.reduce(function (a, b) {
@@ -923,6 +1029,7 @@ describe('Array', function () {
                 delete testSubject.reduce;
                 expect(testSubject).toEqual(copy);
             });
+
             it('should skip non-set values', function () {
                 delete testSubject[1];
                 var visited = {};
@@ -934,10 +1041,12 @@ describe('Array', function () {
 
                 expect(visited).toEqual({ 1: true, 3: true });
             });
+
             it('should have the right length', function () {
                 expect(testSubject.reduce.length).toBe(1);
             });
         });
+
         it('should have a boxed object as list argument of callback', function () {
             var actual;
             Array.prototype.reduce.call('foo', function (accumulator, item, index, list) {
@@ -947,7 +1056,7 @@ describe('Array', function () {
             expect(toStr.call(actual)).toBe('[object String]');
         });
     });
-    describe('reduceRight', function () {
+    describe('#reduceRight()', function () {
         beforeEach(function () {
             testSubject = [1, 2, 3];
         });
@@ -958,16 +1067,18 @@ describe('Array', function () {
                 testSubject.reduceRight(spy);
                 expect(spy.calls[0].args).toExactlyMatch([3, 2, 1, testSubject]);
             });
+
             it('should start with the right initialValue', function () {
                 var spy = jasmine.createSpy().andReturn(0);
                 testSubject.reduceRight(spy, 0);
                 expect(spy.calls[0].args).toExactlyMatch([0, 3, 2, testSubject]);
             });
+
             it('should not affect elements added to the array after it has begun', function () {
-                var arr = [1, 2, 3],
-                    i = 0;
+                var arr = [1, 2, 3];
+                var i = 0;
                 arr.reduceRight(function (a, b) {
-                    i++;
+                    i += 1;
                     if (i <= 4) {
                         arr.push(a + 3);
                     }
@@ -976,6 +1087,7 @@ describe('Array', function () {
                 expect(arr).toEqual([1, 2, 3, 6, 5]);
                 expect(i).toBe(2);
             });
+
             it('should work as expected for empty arrays', function () {
                 var spy = jasmine.createSpy();
                 expect(function () {
@@ -983,24 +1095,28 @@ describe('Array', function () {
                 }).toThrow();
                 expect(spy).not.toHaveBeenCalled();
             });
+
             it('should work as expected for empty arrays with an initial value', function () {
-                var spy = jasmine.createSpy(),
-                    result;
+                var spy = jasmine.createSpy();
+                var result;
 
                 result = [].reduceRight(spy, '');
                 expect(spy).not.toHaveBeenCalled();
                 expect(result).toBe('');
             });
+
             it('should throw correctly if no callback is given', function () {
                 expect(function () {
                     testSubject.reduceRight();
                 }).toThrow();
             });
+
             it('should return the expected result', function () {
                 expect(testSubject.reduceRight(function (a, b) {
                     return String(a || '') + String(b || '');
                 })).toBe('321');
             });
+
             it('should not directly affect the passed array', function () {
                 var copy = testSubject.slice();
                 testSubject.reduceRight(function (a, b) {
@@ -1008,6 +1124,7 @@ describe('Array', function () {
                 });
                 expect(testSubject).toEqual(copy);
             });
+
             it('should skip non-set values', function () {
                 delete testSubject[1];
                 var visited = {};
@@ -1019,6 +1136,7 @@ describe('Array', function () {
 
                 expect(visited).toEqual({ 1: true, 3: true });
             });
+
             it('should have the right length', function () {
                 expect(testSubject.reduceRight.length).toBe(1);
             });
@@ -1028,21 +1146,24 @@ describe('Array', function () {
                 testSubject = createArrayLikeFromArray(testSubject);
                 testSubject.reduceRight = Array.prototype.reduceRight;
             });
+
             it('should pass the correct arguments to the callback', function () {
                 var spy = jasmine.createSpy().andReturn(0);
                 testSubject.reduceRight(spy);
                 expect(spy.calls[0].args).toExactlyMatch([3, 2, 1, testSubject]);
             });
+
             it('should start with the right initialValue', function () {
                 var spy = jasmine.createSpy().andReturn(0);
                 testSubject.reduceRight(spy, 0);
                 expect(spy.calls[0].args).toExactlyMatch([0, 3, 2, testSubject]);
             });
+
             it('should not affect elements added to the array after it has begun', function () {
-                var arr = createArrayLikeFromArray([1, 2, 3]),
-                    i = 0;
+                var arr = createArrayLikeFromArray([1, 2, 3]);
+                var i = 0;
                 Array.prototype.reduceRight.call(arr, function (a, b) {
-                    i++;
+                    i += 1;
                     if (i <= 4) {
                         arr[i + 2] = a + 3;
                     }
@@ -1058,6 +1179,7 @@ describe('Array', function () {
                 });
                 expect(i).toBe(2);
             });
+
             it('should work as expected for empty arrays', function () {
                 var spy = jasmine.createSpy();
                 expect(function () {
@@ -1065,16 +1187,19 @@ describe('Array', function () {
                 }).toThrow();
                 expect(spy).not.toHaveBeenCalled();
             });
+
             it('should throw correctly if no callback is given', function () {
                 expect(function () {
                     testSubject.reduceRight();
                 }).toThrow();
             });
+
             it('should return the expected result', function () {
                 expect(testSubject.reduceRight(function (a, b) {
                     return String(a || '') + String(b || '');
-                })).toEqual('321');
+                })).toBe('321');
             });
+
             it('should not directly affect the passed array', function () {
                 var copy = createArrayLikeFromArray(testSubject);
                 testSubject.reduceRight(function (a, b) {
@@ -1083,6 +1208,7 @@ describe('Array', function () {
                 delete testSubject.reduceRight;
                 expect(testSubject).toEqual(copy);
             });
+
             it('should skip non-set values', function () {
                 delete testSubject[1];
                 var visited = {};
@@ -1094,10 +1220,12 @@ describe('Array', function () {
 
                 expect(visited).toEqual({ 1: true, 3: true });
             });
+
             it('should have the right length', function () {
                 expect(testSubject.reduceRight.length).toBe(1);
             });
         });
+
         it('should have a boxed object as list argument of callback', function () {
             var actual;
             Array.prototype.reduceRight.call('foo', function (accumulator, item, index, list) {
@@ -1108,7 +1236,7 @@ describe('Array', function () {
         });
     });
 
-    describe('isArray', function () {
+    describe('.isArray()', function () {
         it('should be true for Array', function () {
             expect(Array.isArray([])).toBe(true);
         });
@@ -1154,13 +1282,59 @@ describe('Array', function () {
         }
     });
 
-    describe('unshift', function () {
+    describe('#shift()', function () {
+        it('works on arrays', function () {
+            var arr = [1, 2];
+            var result = arr.shift();
+            expect(result).toBe(1);
+            expect(arr.length).toBe(1);
+            expect(Object.prototype.hasOwnProperty.call(arr, 0)).toBe(true);
+            expect(Object.prototype.hasOwnProperty.call(arr, 1)).toBe(false);
+            expect(arr[0]).toBe(2);
+            expect(arr[1]).toBeUndefined();
+        });
+
+        it('is generic', function () {
+            var obj = { 0: 1, 1: 2, length: 2 };
+            var result = Array.prototype.shift.call(obj);
+            expect(result).toBe(1);
+            expect(obj.length).toBe(1);
+            expect(Object.prototype.hasOwnProperty.call(obj, 0)).toBe(true);
+            expect(Object.prototype.hasOwnProperty.call(obj, 1)).toBe(false);
+            expect(obj[0]).toBe(2);
+            expect(obj[1]).toBeUndefined();
+        });
+    });
+
+    describe('#unshift()', function () {
         it('should return length', function () {
             expect([].unshift(0)).toBe(1);
         });
+
+        it('works on arrays', function () {
+            var arr = [1];
+            var result = arr.unshift(undefined);
+            expect(result).toBe(2);
+            expect(arr.length).toBe(2);
+            expect(Object.prototype.hasOwnProperty.call(arr, 0)).toBe(true);
+            expect(Object.prototype.hasOwnProperty.call(arr, 1)).toBe(true);
+            expect(arr[0]).toBeUndefined();
+            expect(arr[1]).toBe(1);
+        });
+
+        it('is generic', function () {
+            var obj = { 0: 1, length: 1 };
+            var result = Array.prototype.unshift.call(obj, undefined);
+            expect(result).toBe(2);
+            expect(obj.length).toBe(2);
+            expect(Object.prototype.hasOwnProperty.call(obj, 0)).toBe(true);
+            expect(Object.prototype.hasOwnProperty.call(obj, 1)).toBe(true);
+            expect(obj[0]).toBeUndefined();
+            expect(obj[1]).toBe(1);
+        });
     });
 
-    describe('splice', function () {
+    describe('#splice()', function () {
         var b = ['b'];
         var a = [1, 'a', b];
         var test;
@@ -1292,7 +1466,7 @@ describe('Array', function () {
             expect(obj[0]).toBe(1);
         });
 
-        it('should not break on sparse arrays in Opera', function () {
+        ifHasDenseUndefinedsIt('should not break on sparse arrays in Opera', function () {
             // test from https://github.com/wikimedia/VisualEditor/blob/d468b00311e69c2095b9da360c5745153342a5c3/src/ve.utils.js#L182-L196
             var n = 256;
             var arr = [];
@@ -1301,7 +1475,7 @@ describe('Array', function () {
             expect(arr[n]).toBe('a');
         });
 
-        it('should not break on sparse arrays in Safari 7/8', function () {
+        ifHasDenseUndefinedsIt('should not break on sparse arrays in Safari 7/8', function () {
             // test from https://github.com/wikimedia/VisualEditor/blob/d468b00311e69c2095b9da360c5745153342a5c3/src/ve.utils.js#L182-L196
             var justFine = new Array(1e5 - 1);
             justFine[10] = 'x';
@@ -1317,4 +1491,472 @@ describe('Array', function () {
         });
     });
 
+    describe('#join()', function () {
+        it('defaults to a comma separator when none is provided', function () {
+            expect([1, 2].join()).toBe('1,2');
+        });
+
+        it('defaults to a comma separator when undefined is provided', function () {
+            expect([1, 2].join(undefined)).toBe('1,2');
+        });
+
+        it('works, extended', function () {
+            expect([].join()).toBe('');
+            expect([undefined].join()).toBe('');
+            expect([undefined, undefined].join()).toBe(',');
+            expect([null, null].join()).toBe(',');
+            expect([undefined, undefined].join('|')).toBe('|');
+            expect([null, null].join('|')).toBe('|');
+            expect([1, 2, 3].join('|')).toBe('1|2|3');
+            expect([1, 2, 3].join(null)).toBe('1null2null3');
+            expect([1, 2, 3].join({})).toBe('1[object Object]2[object Object]3');
+            expect([1, 2, 3].join('')).toBe('123');
+        });
+
+        it('is generic', function () {
+            var obj = { 0: 1, 1: 2, 2: 3, 3: 4, length: 3 };
+            expect(Array.prototype.join.call(obj, ',')).toBe('1,2,3');
+        });
+
+        it('works with a string literal', function () {
+            var str = '123';
+            expect(Array.prototype.join.call(str, ',')).toBe('1,2,3');
+        });
+
+        it('works with `arguments`', function () {
+            var args = (function () { return arguments; }(1, 2, 3));
+            expect(Array.prototype.join.call(args, ',')).toBe('1,2,3');
+        });
+    });
+
+    describe('#push()', function () {
+        it('works on arrays', function () {
+            var arr = [];
+            var result = arr.push(undefined);
+            expect(result).toBe(1);
+            expect(arr.length).toBe(1);
+            expect(Object.prototype.hasOwnProperty.call(arr, 0)).toBe(true);
+            expect(arr[0]).toBeUndefined();
+        });
+
+        it('is generic', function () {
+            var obj = {};
+            var result = Array.prototype.push.call(obj, undefined);
+            expect(result).toBe(1);
+            expect(obj.length).toBe(1);
+            expect(Object.prototype.hasOwnProperty.call(obj, 0)).toBe(true);
+            expect(obj[0]).toBeUndefined();
+        });
+    });
+
+    describe('#pop()', function () {
+        it('works on arrays', function () {
+            var arr = [1, 2, 3];
+            var result = arr.pop();
+            expect(result).toBe(3);
+            expect(arr.length).toBe(2);
+            expect(Object.prototype.hasOwnProperty.call(arr, 2)).toBe(false);
+            expect(arr[2]).toBeUndefined();
+        });
+
+        it('is generic', function () {
+            var obj = { 0: 1, 1: 2, 2: 3, length: 3 };
+            var result = Array.prototype.pop.call(obj);
+            expect(result).toBe(3);
+            expect(obj.length).toBe(2);
+            expect(Object.prototype.hasOwnProperty.call(obj, 2)).toBe(false);
+            expect(obj[2]).toBeUndefined();
+        });
+    });
+
+    describe('#slice()', function () {
+        it('works on arrays', function () {
+            var arr = [1, 2, 3, 4];
+            var result = arr.slice(1, 3);
+            expect(result).toEqual([2, 3]);
+        });
+
+        it('is generic', function () {
+            var obj = { 0: 1, 1: 2, 2: 3, 3: 4, length: 4 };
+            var result = Array.prototype.slice.call(obj, 1, 3);
+            expect(result).toEqual([2, 3]);
+        });
+
+        it('works with `arguments`', function () {
+            var obj = (function () {
+              return arguments;
+            }(1, 2, 3, 4));
+            var result = Array.prototype.slice.call(obj, 1, 3);
+            expect(result).toEqual([2, 3]);
+        });
+
+        it('boxed string access', function () {
+            var obj = '1234';
+            var result = Array.prototype.slice.call(obj, 1, 3);
+            expect(result).toEqual(['2', '3']);
+        });
+    });
+
+    describe('#sort()', function () {
+        describe('usage', function () {
+            it('requires a function or undefined as first argument', function () {
+                var actual = [1, 2];
+                expect(actual.sort()).toBe(actual);
+                expect(actual.sort(undefined)).toBe(actual);
+                expect(actual.sort(function () { return 0; })).toBe(actual);
+            });
+
+            it('requires a non-function or non-undefined to throw a `TypeError`', function () {
+                expect(function () { [1, 2].sort(null); }).toThrow();
+                expect(function () { [1, 2].sort(1); }).toThrow();
+                expect(function () { [1, 2].sort(''); }).toThrow();
+                expect(function () { [1, 2].sort(true); }).toThrow();
+                expect(function () { [1, 2].sort({}); }).toThrow();
+                expect(function () { [1, 2].sort([]); }).toThrow();
+                expect(function () { [1, 2].sort(new Date()); }).toThrow();
+                expect(function () { [1, 2].sort(/pattern/); }).toThrow();
+            });
+        });
+
+        describe('ascending', function () {
+            it('[5,2,4,6,1,3] should result in [1,2,3,4,5,6]', function () {
+                var actual = [5, 2, 4, 6, 1, 3];
+                var expected = [1, 2, 3, 4, 5, 6];
+                actual.sort();
+                expect(actual).toEqual(expected);
+            });
+
+            it('[5,2,2,6,1,3] should result in [1,2,2,3,5,6]', function () {
+                var actual = [5, 2, 2, 6, 1, 3];
+                var expected = [1, 2, 2, 3, 5, 6];
+                actual.sort();
+                expect(actual).toEqual(expected);
+            });
+
+            it('[0,0,0,0,0,1] should result in [0,0,0,0,0,1]', function () {
+                var actual = [0, 0, 0, 0, 0, 1];
+                var expected = [0, 0, 0, 0, 0, 1];
+                actual.sort();
+                expect(actual).toEqual(expected);
+            });
+
+            it('[0,0,0,0,0,-1] should result in [-1,0,0,0,0,0]', function () {
+                var actual = [0, 0, 0, 0, 0, -1];
+                var expected = [-1, 0, 0, 0, 0, 0];
+                actual.sort();
+                expect(actual).toEqual(expected);
+            });
+
+            it('[f,e,d,a,c,b] should result in [a,b,c,d,e,f]', function () {
+                var actual = ['f', 'e', 'd', 'a', 'c', 'b'];
+                var expected = ['a', 'b', 'c', 'd', 'e', 'f'];
+                actual.sort();
+                expect(actual).toEqual(expected);
+            });
+
+            it('[f,e,d,,,,a,c,b] should result in [a,b,c,d,e,f,,,]', function () {
+                var actual = ['f', 'e', 'd', 1, 2, 'a', 'c', 'b'];
+                delete actual[3];
+                delete actual[4];
+                var expected = ['a', 'b', 'c', 'd', 'e', 'f'];
+                expected.length = 8;
+                actual.sort();
+                expect(actual).toEqual(expected);
+            });
+
+            it('[f,e,d,,null,,a,c,b] should result in [a,b,c,d,e,f,null,,,]', function () {
+                var actual = ['f', 'e', 'd', 1, null, 2, 'a', 'c', 'b'];
+                delete actual[3];
+                delete actual[5];
+                var expected = ['a', 'b', 'c', 'd', 'e', 'f', null];
+                expected.length = 9;
+                actual.sort();
+                expect(actual).toEqual(expected);
+            });
+
+            it('[f,e,d,,null,undefined,a,c,b] should result in [a,b,c,d,e,f,null,undefined,,]', function () {
+                var actual = ['f', 'e', 'd', 1, null, undefined, 'a', 'c', 'b'];
+                delete actual[3];
+                var expected = ['a', 'b', 'c', 'd', 'e', 'f', null, undefined];
+                expected.length = 9;
+                actual.sort();
+                expect(actual).toEqual(expected);
+            });
+
+            it('[] should result in []', function () {
+                var actual = [];
+                var expected = [];
+                actual.sort();
+                expect(actual).toEqual(expected);
+            });
+
+            it('[1] should result in [1]', function () {
+                var actual = [1];
+                var expected = [1];
+                actual.sort();
+                expect(actual).toEqual(expected);
+            });
+
+            it('result should find only greater or equal values', function () {
+                var actual = [];
+                var i;
+                for (i = 0; i < 100; i += 1) {
+                    actual.push(('00' + (Math.random() * 100).toFixed(0)).slice(-3));
+                }
+                actual.sort();
+                for (i = 0; i < actual.length - 1; i += 1) {
+                    expect(actual[i] <= actual[i + 1]).toBe(true);
+                }
+            });
+        });
+
+        describe('descending', function () {
+            var descending = function (left, right) {
+                var leftS = String(left);
+                var rightS = String(right);
+                if (leftS === rightS) {
+                    return +0;
+                }
+                if (leftS < rightS) {
+                    return 1;
+                }
+                return -1;
+            };
+
+            it('[5,2,4,6,1,3] should result in [6,5,4,3,2,1]', function () {
+                var actual = [5, 2, 4, 6, 1, 3];
+                var expected = [6, 5, 4, 3, 2, 1];
+                actual.sort(descending);
+                expect(actual).toEqual(expected);
+            });
+
+            it('[5,2,2,6,1,3] should result in [6,5,4,2,2,1]', function () {
+                var actual = [5, 2, 2, 6, 1, 3];
+                var expected = [6, 5, 3, 2, 2, 1];
+                actual.sort(descending);
+                expect(actual).toEqual(expected);
+            });
+
+            it('[0,0,0,0,0,1] should result in [1,0,0,0,0,0]', function () {
+                var actual = [0, 0, 0, 0, 0, 1];
+                var expected = [1, 0, 0, 0, 0, 0];
+                actual.sort(descending);
+                expect(actual).toEqual(expected);
+            });
+
+            it('[0,0,0,0,0,-1] should result in [0,0,0,0,0,-1]', function () {
+                var actual = [0, 0, 0, 0, 0, -1];
+                var expected = [0, 0, 0, 0, 0, -1];
+                actual.sort(descending);
+                expect(actual).toEqual(expected);
+            });
+
+            it('[f,e,d,a,c,b] should result in [f,e,d,c,b,a]', function () {
+                var actual = ['f', 'e', 'd', 'a', 'c', 'b'];
+                var expected = ['f', 'e', 'd', 'c', 'b', 'a'];
+                actual.sort(descending);
+                expect(actual).toEqual(expected);
+            });
+
+            it('[f,e,d,,,a,c,b] should result in [f,e,d,c,b,a,,,]', function () {
+                var actual = ['f', 'e', 'd', 1, 2, 'a', 'c', 'b'];
+                delete actual[3];
+                delete actual[4];
+                var expected = ['f', 'e', 'd', 'c', 'b', 'a'];
+                expected.length = 8;
+                actual.sort(descending);
+                expect(actual).toEqual(expected);
+            });
+
+            it('[f,e,d,,null,,a,c,b] should result in [null,f,e,d,c,b,a,,,]', function () {
+                var actual = ['f', 'e', 'd', 1, null, 2, 'a', 'c', 'b'];
+                delete actual[3];
+                delete actual[5];
+                var expected = [null, 'f', 'e', 'd', 'c', 'b', 'a'];
+                expected.length = 9;
+                actual.sort(descending);
+                expect(actual).toEqual(expected);
+            });
+
+            it('[f,e,d,undefined,null,,a,c,b] should result in [null,f,e,d,c,b,a,undefined,,]', function () {
+                var actual = ['f', 'e', 'd', undefined, null, 2, 'a', 'c', 'b'];
+                delete actual[5];
+                var expected = [null, 'f', 'e', 'd', 'c', 'b', 'a', undefined];
+                expected.length = 9;
+                actual.sort(descending);
+                expect(actual).toEqual(expected);
+            });
+
+            it('[] should result in []', function () {
+                var actual = [];
+                var expected = [];
+                actual.sort(descending);
+                expect(actual).toEqual(expected);
+            });
+
+            it('[1] should result in [1]', function () {
+                var actual = [1];
+                var expected = [1];
+                actual.sort(descending);
+                expect(actual).toEqual(expected);
+            });
+
+            it('result should find only lesser or equal values', function () {
+                var actual = [];
+                var i;
+                for (i = 0; i < 100; i += 1) {
+                    actual.push(('00' + (Math.random() * 100).toFixed(0)).slice(-3));
+                }
+                actual.sort(descending);
+                for (i = 0; i < actual.length - 1; i += 1) {
+                    expect(actual[i] >= actual[i + 1]).toBe(true);
+                }
+            });
+        });
+
+        describe('returned value', function () {
+            it('should be the source object', function () {
+                var actual = [1, 3, 2];
+                expect(actual.sort()).toBe(actual);
+            });
+        });
+
+        describe('when used generically', function () {
+            var descending = function (left, right) {
+                var leftS = String(left);
+                var rightS = String(right);
+                if (leftS === rightS) {
+                    return +0;
+                }
+                if (leftS < rightS) {
+                    return 1;
+                }
+                return -1;
+            };
+
+            var args = function () {
+                return arguments;
+            };
+
+            it('should not sort objects without length', function () {
+                var actual = {
+                    0: 5,
+                    1: 2,
+                    2: 4,
+                    3: 6,
+                    4: 1,
+                    5: 3
+                };
+                var expected = {
+                    0: 5,
+                    1: 2,
+                    2: 4,
+                    3: 6,
+                    4: 1,
+                    5: 3
+                };
+                Array.prototype.sort.call(actual);
+                expect(actual).toEqual(expected);
+                Array.prototype.sort.call(actual, descending);
+                expect(actual).toEqual(expected);
+            });
+
+            it('should sort objects ascending with length', function () {
+                    var actual = {
+                        0: 5,
+                        1: 2,
+                        2: 4,
+                        3: 6,
+                        4: 1,
+                        5: 3,
+                        length: 6
+                    };
+                    var expected = {
+                        0: 1,
+                        1: 2,
+                        2: 3,
+                        3: 4,
+                        4: 5,
+                        5: 6,
+                        length: 6
+                    };
+                    Array.prototype.sort.call(actual);
+                    expect(actual).toEqual(expected);
+            });
+
+            it('should sort objects descending with length', function () {
+                    var actual = {
+                        0: 5,
+                        1: 2,
+                        2: 4,
+                        3: 6,
+                        4: 1,
+                        5: 3,
+                        length: 6
+                    };
+                    var expected = {
+                        0: 6,
+                        1: 5,
+                        2: 4,
+                        3: 3,
+                        4: 2,
+                        5: 1,
+                        length: 6
+                    };
+                    Array.prototype.sort.call(actual, descending);
+                    expect(actual).toEqual(expected);
+            });
+
+            it('should sort objects descending with mixed content types and with length', function () {
+                var actual = {
+                    0: 5,
+                    1: 2,
+                    2: 4,
+                    4: null,
+                    6: 1,
+                    7: 3,
+                    length: 8
+                };
+                var expected = {
+                    0: null,
+                    1: 5,
+                    2: 4,
+                    3: 3,
+                    4: 2,
+                    5: 1,
+                    length: 8
+                };
+                Array.prototype.sort.call(actual, descending);
+                expect(actual).toEqual(expected);
+            });
+
+            it('should sort `arguments` object ascending', function () {
+                var actual = args(5, 2, 4, 6, 1, 3);
+                var expected = args(1, 2, 3, 4, 5, 6);
+                Array.prototype.sort.call(actual);
+                expect(actual).toEqual(expected);
+            });
+
+            it('should sort `arguments` object ascending with mixed content types', function () {
+                var actual = args(5, 2, 4, null, 1, 3);
+                var expected = args(1, 2, 3, 4, 5, null);
+                Array.prototype.sort.call(actual);
+                expect(actual).toEqual(expected);
+            });
+
+            it('should sort `arguments` object descending', function () {
+                var actual = args(5, 2, 4, 6, 1, 3);
+                var expected = args(6, 5, 4, 3, 2, 1);
+                Array.prototype.sort.call(actual, descending);
+                expect(actual).toEqual(expected);
+            });
+
+            it('should sort `arguments` object descending with mixed content types', function () {
+                var actual = args(5, 2, 4, null, 1, 3);
+                var expected = args(null, 5, 4, 3, 2, 1);
+                Array.prototype.sort.call(actual, descending);
+                expect(actual).toEqual(expected);
+            });
+        });
+    });
 });
diff --git a/tests/spec/s-date.js b/tests/spec/s-date.js
index 49858f9..c43d64b 100644
--- a/tests/spec/s-date.js
+++ b/tests/spec/s-date.js
@@ -16,7 +16,7 @@ describe('Date', function () {
     var ifSupportsDescriptorsIt = supportsDescriptors ? it : xit;
     var has = Object.prototype.hasOwnProperty;
 
-    describe('now', function () {
+    describe('.now()', function () {
         it('should be the current time', function () {
             var before = (new Date()).getTime();
             var middle = Date.now();
@@ -49,7 +49,8 @@ describe('Date', function () {
         });
 
         it('works as a function', function () {
-          expect(Date(0)).toBe(String(Date(0)));
+          var zeroDate = Date(0);
+          expect(zeroDate).toBe(String(zeroDate));
           var value = Date(1441705534578);
           expect(value).toBe(String(value));
         });
@@ -75,7 +76,7 @@ describe('Date', function () {
         });
     });
 
-    describe('parse', function () {
+    describe('.parse()', function () {
         // TODO: Write the rest of the test.
 
         ifSupportsDescriptorsIt('is not enumerable', function () {
@@ -167,13 +168,13 @@ describe('Date', function () {
             var actual = Number(new Date(1970, 0));
             var expected = parseInt(actual, 10);
             expect(actual).toBeDefined();
-            expect(actual).toEqual(expected);
+            expect(actual).toBe(expected);
             expect(isNaN(actual)).toBeFalsy();
         });
 
     });
 
-    describe('toString', function () {
+    describe('#toString()', function () {
         var actual;
 
         beforeEach(function () {
@@ -188,7 +189,7 @@ describe('Date', function () {
         });
     });
 
-    describe('valueOf', function () {
+    describe('#valueOf()', function () {
         // Note that new Date(1970, 0).valueOf() is 0 in UTC timezone.
         // Check check that it's a number (and an int), not that it's "truthy".
         var actual;
@@ -207,14 +208,14 @@ describe('Date', function () {
         });
     });
 
-    describe('getUTCDate', 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);
         });
     });
 
-    describe('getUTCMonth', function () {
+    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);
@@ -226,7 +227,7 @@ describe('Date', function () {
         });
     });
 
-    describe('toISOString', function () {
+    describe('#toISOString()', function () {
         // TODO: write the rest of the test.
 
         it('should support extended years', function () {
@@ -241,7 +242,7 @@ describe('Date', function () {
 
     });
 
-    describe('toJSON', function () {
+    describe('#toJSON()', function () {
 
         // Opera 11.6x/12 bug
         it('should call toISOString', function () {
diff --git a/tests/spec/s-error.js b/tests/spec/s-error.js
new file mode 100644
index 0000000..7f38bab
--- /dev/null
+++ b/tests/spec/s-error.js
@@ -0,0 +1,50 @@
+/* global describe, it, xit, expect */
+
+describe('Error', function () {
+    'use strict';
+
+    var supportsDescriptors = Object.defineProperty && (function () {
+        try {
+            var obj = {};
+            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;
+        }
+    }());
+    var ifSupportsDescriptorsIt = supportsDescriptors ? it : xit;
+
+    describe('#toString()', function () {
+        it('stringifies a newed error properly', function () {
+            var msg = 'test';
+            var error = new RangeError(msg);
+            expect(error.name).toBe('RangeError');
+            expect(error.message).toBe(msg);
+            expect(String(error)).toBe(error.name + ': ' + msg);
+        });
+
+        it('stringifies a thrown error properly', function () {
+            var msg = 'test';
+            var error;
+            try {
+                throw new RangeError(msg);
+            } catch (e) {
+                error = e;
+            }
+            expect(error.name).toBe('RangeError');
+            expect(error.message).toBe(msg);
+            expect(String(error)).toBe(error.name + ': ' + msg);
+        });
+    });
+
+    describe('enumerability of prototype properties', function () {
+        ifSupportsDescriptorsIt('#message', function () {
+            expect(Object.prototype.propertyIsEnumerable.call(Error.prototype, 'message')).toBe(false);
+        });
+
+        ifSupportsDescriptorsIt('#name', function () {
+            expect(Object.prototype.propertyIsEnumerable.call(Error.prototype, 'name')).toBe(false);
+        });
+    });
+});
diff --git a/tests/spec/s-function.js b/tests/spec/s-function.js
index de84946..97237ad 100644
--- a/tests/spec/s-function.js
+++ b/tests/spec/s-function.js
@@ -3,7 +3,7 @@
 describe('Function', function () {
     'use strict';
 
-    describe('apply', function () {
+    describe('#apply()', function () {
         it('works with arraylike objects', function () {
             var arrayLike = { length: 4, 0: 1, 2: 4, 3: true };
             var expectedArray = [1, undefined, 4, true];
@@ -14,7 +14,7 @@ describe('Function', function () {
         });
     });
 
-    describe('bind', function () {
+    describe('#bind()', function () {
         var actual;
 
         var testSubject = {
diff --git a/tests/spec/s-global.js b/tests/spec/s-global.js
index 81f03c6..4c0c97a 100644
--- a/tests/spec/s-global.js
+++ b/tests/spec/s-global.js
@@ -8,6 +8,8 @@ describe('global methods', function () {
     var ifFunctionsHaveNamesIt = functionsHaveNames ? it : xit;
 
     describe('parseInt', function () {
+        /* eslint-disable radix */
+
         ifFunctionsHaveNamesIt('has the right name', function () {
           expect(parseInt.name).toBe('parseInt');
         });
@@ -46,10 +48,18 @@ describe('global methods', function () {
             expect(parseInt(ws + '0x16')).toBe(parseInt('0x16', 16));
         });
 
-       it('defaults the radix properly when not a true number', function () {
-           var fakeZero = { valueOf: function () { return 0; } };
-           expect(parseInt('08', fakeZero)).toBe(parseInt('08', 10));
-           expect(parseInt('0x16', fakeZero)).toBe(parseInt('0x16', 16));
-       });
+        it('defaults the radix properly when not a true number', function () {
+            var fakeZero = { valueOf: function () { return 0; } };
+            expect(parseInt('08', fakeZero)).toBe(parseInt('08', 10));
+            expect(parseInt('0x16', fakeZero)).toBe(parseInt('0x16', 16));
+        });
+
+        it('allows sign-prefixed hex values', function () {
+            expect(parseInt('-0xF')).toBe(-15);
+            expect(parseInt('-0xF', 16)).toBe(-15);
+            expect(parseInt('+0xF')).toBe(15);
+            expect(parseInt('+0xF', 16)).toBe(15);
+        });
+        /* eslint-enable radix */
     });
 });
diff --git a/tests/spec/s-number.js b/tests/spec/s-number.js
index 9955486..441a7a9 100644
--- a/tests/spec/s-number.js
+++ b/tests/spec/s-number.js
@@ -3,7 +3,7 @@
 describe('Number', function () {
     'use strict';
 
-    describe('toFixed', function () {
+    describe('#toFixed()', function () {
         it('should convert numbers correctly', function () {
             expect((0.00008).toFixed(3)).toBe('0.000');
             expect((0.9).toFixed(0)).toBe('1');
@@ -13,6 +13,28 @@ describe('Number', function () {
         });
     });
 
+    describe('#toPrecision()', function () {
+        // the spec allows for this test to fail.
+        it('throws a RangeError when < 1 or > 21', function () {
+            expect(function () { return (0.9).toPrecision(0); }).toThrow();
+            // Firefox allows values up to 100
+            expect(function () { return (0.9).toPrecision(101); }).toThrow();
+        });
+
+        it('works as expected', function () {
+			expect((0.00008).toPrecision(3)).toBe('0.0000800');
+			expect((1.255).toPrecision(2)).toBe('1.3');
+			expect((1843654265.0774949).toPrecision(13)).toBe('1843654265.077');
+            expect(NaN.toPrecision(1)).toBe('NaN');
+        });
+
+        it('works with an undefined precision', function () {
+            var num = 123.456;
+            expect(num.toPrecision()).toBe(String(num));
+            expect(num.toPrecision(undefined)).toBe(String(num));
+        });
+    });
+
     describe('constants', function () {
         it('should have MAX_VALUE', function () {
             expect(Number.MAX_VALUE).toBe(1.7976931348623157e308);
diff --git a/tests/spec/s-object.js b/tests/spec/s-object.js
index a86878d..3065c66 100644
--- a/tests/spec/s-object.js
+++ b/tests/spec/s-object.js
@@ -1,5 +1,15 @@
 /* global describe, it, xit, expect, beforeEach, jasmine, window */
 
+var supportsDescriptors = Object.defineProperty && (function () {
+    try {
+        var obj = {};
+        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;
+    }
+}());
 var ifWindowIt = typeof window === 'undefined' ? xit : it;
 var extensionsPreventible = typeof Object.preventExtensions === 'function' && (function () {
     var obj = {};
@@ -130,8 +140,8 @@ describe('Object', function () {
         ifWindowIt('can serialize all objects on the `window`', function () {
           var has = Object.prototype.hasOwnProperty;
           var windowItemKeys, exception;
-          var blacklistedKeys = ['window', 'console', 'parent', 'self', 'frame', 'frames', 'frameElement'];
-          if (Object.defineProperty) {
+          var blacklistedKeys = ['window', 'console', 'parent', 'self', 'frame', 'frames', 'frameElement', 'external'];
+          if (supportsDescriptors) {
               Object.defineProperty(window, 'thrower', { configurable: true, get: function () { throw new RangeError('thrower!'); } });
           }
           for (var k in window) {
@@ -142,15 +152,17 @@ describe('Object', function () {
                      } catch (e) {
                          exception = e;
                      }
-                     expect(Array.isArray(windowItemKeys)).toEqual(true);
+                     expect(Array.isArray(windowItemKeys)).toBe(true);
                      expect(exception).toBeUndefined();
               }
           }
-          delete window.thrower;
+          if (supportsDescriptors) {
+             delete window.thrower;
+          }
         });
     });
 
-    describe('Object.isExtensible', function () {
+    describe('.isExtensible()', function () {
         var obj = { };
 
         it('should return true if object is extensible', function () {
@@ -179,7 +191,7 @@ describe('Object', function () {
         });
     });
 
-    describe('Object.defineProperty', function () {
+    describe('.defineProperty()', function () {
         var obj;
 
         beforeEach(function () {
@@ -234,7 +246,7 @@ describe('Object', function () {
         });
     });
 
-    describe('Object.getOwnPropertyDescriptor', function () {
+    describe('.getOwnPropertyDescriptor()', function () {
         it('should return undefined because the object does not own the property', function () {
             var descr = Object.getOwnPropertyDescriptor({}, 'name');
 
@@ -243,12 +255,14 @@ describe('Object', function () {
 
         it('should return a data descriptor', function () {
             var descr = Object.getOwnPropertyDescriptor({ name: 'Testing' }, 'name');
+            var expected = {
+                value: 'Testing',
+                enumerable: true,
+                writable: true,
+                configurable: true
+            };
 
-            expect(descr).not.toBeUndefined();
-            expect(descr.value).toBe('Testing');
-            expect(descr.writable).toBe(true);
-            expect(descr.enumerable).toBe(true);
-            expect(descr.configurable).toBe(true);
+            expect(descr).toEqual(expected);
         });
 
         it('should return undefined because the object does not own the property', function () {
@@ -258,22 +272,17 @@ describe('Object', function () {
         });
 
         it('should return a data descriptor', function () {
-            var obj = Object.create({}, {
-                name: {
-                    value: 'Testing',
-                    configurable: true,
-                    enumerable: true,
-                    writable: true
-                }
-            });
+            var expected = {
+                value: 'Testing',
+                configurable: true,
+                enumerable: true,
+                writable: true
+            };
+            var obj = Object.create({}, { name: expected });
 
             var descr = Object.getOwnPropertyDescriptor(obj, 'name');
 
-            expect(descr).not.toBeUndefined();
-            expect(descr.value).toBe('Testing');
-            expect(descr.writable).toBe(true);
-            expect(descr.enumerable).toBe(true);
-            expect(descr.configurable).toBe(true);
+            expect(descr).toEqual(expected);
         });
 
         it('should throw error for non object', function () {
@@ -286,7 +295,7 @@ describe('Object', function () {
         });
     });
 
-    describe('Object.getPrototypeOf', function () {
+    describe('.getPrototypeOf()', function () {
         it('should return the [[Prototype]] of an object', function () {
             var Foo = function () {};
 
@@ -320,11 +329,11 @@ describe('Object', function () {
         it('should return null on Object.create(null)', function () {
             var obj = Object.create(null);
 
-            expect(Object.getPrototypeOf(obj)).toBe(null);
+            expect(Object.getPrototypeOf(obj) === null).toBe(true);
         });
     });
 
-    describe('Object.defineProperties', function () {
+    describe('.defineProperties()', function () {
         it('should define the constructor property', function () {
             var target = {};
             var newProperties = {
@@ -333,11 +342,11 @@ describe('Object', function () {
                 }
             };
             Object.defineProperties(target, newProperties);
-            expect(target.constructor).toEqual('new constructor');
+            expect(target.constructor).toBe('new constructor');
         });
     });
 
-    describe('Object.create', function () {
+    describe('.create()', function () {
         it('should create objects with no properties when called as `Object.create(null)`', function () {
             var obj = Object.create(null);
 
diff --git a/tests/spec/s-regexp.js b/tests/spec/s-regexp.js
new file mode 100644
index 0000000..a336602
--- /dev/null
+++ b/tests/spec/s-regexp.js
@@ -0,0 +1,27 @@
+/* global describe, it, expect */
+
+describe('RegExp', function () {
+    'use strict';
+
+    describe('#toString()', function () {
+        describe('literals', function () {
+          it('should return correct flags and in correct order', function () {
+              expect(String(/pattern/)).toBe('/pattern/');
+              expect(String(/pattern/i)).toBe('/pattern/i');
+              expect(String(/pattern/mi)).toBe('/pattern/im');
+              expect(String(/pattern/im)).toBe('/pattern/im');
+              expect(String(/pattern/mgi)).toBe('/pattern/gim');
+          });
+        });
+
+        describe('objects', function () {
+          it('should return correct flags and in correct order', function () {
+              expect(String(new RegExp('pattern'))).toBe('/pattern/');
+              expect(String(new RegExp('pattern', 'i'))).toBe('/pattern/i');
+              expect(String(new RegExp('pattern', 'mi'))).toBe('/pattern/im');
+              expect(String(new RegExp('pattern', 'im'))).toBe('/pattern/im');
+              expect(String(new RegExp('pattern', 'mgi'))).toBe('/pattern/gim');
+          });
+        });
+    });
+});
diff --git a/tests/spec/s-string.js b/tests/spec/s-string.js
index 5e5f6e6..8f15157 100644
--- a/tests/spec/s-string.js
+++ b/tests/spec/s-string.js
@@ -3,11 +3,11 @@
 describe('String', function () {
     'use strict';
 
-    describe('trim', function () {
+    describe('#trim()', function () {
         var test = '\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFFHello, World!\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF';
 
         it('trims all ES5 whitespace', function () {
-            expect(test.trim()).toEqual('Hello, World!');
+            expect(test.trim()).toBe('Hello, World!');
             expect(test.trim().length).toBe(13);
         });
 
@@ -17,7 +17,7 @@ describe('String', function () {
         });
     });
 
-    describe('replace', function () {
+    describe('#replace()', function () {
         it('returns undefined for non-capturing groups', function () {
             var groups = [];
             'x'.replace(/x(.)?/g, function (m, group) {
@@ -37,7 +37,7 @@ describe('String', function () {
         });
     });
 
-    describe('split', function () {
+    describe('#split()', function () {
         var test = 'ab';
 
         it('If "separator" is undefined must return Array with one String - "this" string', function () {
@@ -232,34 +232,34 @@ describe('String', function () {
 
     describe('#indexOf()', function () {
       it('has basic support', function () {
-          expect('abcab'.indexOf('a')).toEqual(0);
-          expect('abcab'.indexOf('a', 1)).toEqual(3);
-          expect('abcab'.indexOf('a', 4)).toEqual(-1);
+          expect('abcab'.indexOf('a')).toBe(0);
+          expect('abcab'.indexOf('a', 1)).toBe(3);
+          expect('abcab'.indexOf('a', 4)).toBe(-1);
       });
 
       it('works with unicode', function () {
-          expect('あいabcあいabc'.indexOf('あい')).toEqual(0);
-          expect('あいabcあいabc'.indexOf('あい', 0)).toEqual(0);
-          expect('あいabcあいabc'.indexOf('あい', 1)).toEqual(5);
-          expect('あいabcあいabc'.indexOf('あい', 6)).toEqual(-1);
+          expect('あいabcあいabc'.indexOf('あい')).toBe(0);
+          expect('あいabcあいabc'.indexOf('あい', 0)).toBe(0);
+          expect('あいabcあいabc'.indexOf('あい', 1)).toBe(5);
+          expect('あいabcあいabc'.indexOf('あい', 6)).toBe(-1);
       });
     });
 
     describe('#lastIndexOf()', function () {
       it('has the right length', function () {
-          expect(String.prototype.lastIndexOf.length).toEqual(1);
+          expect(String.prototype.lastIndexOf.length).toBe(1);
       });
 
       it('has basic support', function () {
-          expect('abcd'.lastIndexOf('d')).toEqual(3);
-          expect('abcd'.lastIndexOf('d', 3)).toEqual(3);
-          expect('abcd'.lastIndexOf('d', 2)).toEqual(-1);
+          expect('abcd'.lastIndexOf('d')).toBe(3);
+          expect('abcd'.lastIndexOf('d', 3)).toBe(3);
+          expect('abcd'.lastIndexOf('d', 2)).toBe(-1);
       });
 
       it('works with unicode', function () {
-          expect('abcあい'.lastIndexOf('あい')).toEqual(3);
-          expect('abcあい'.lastIndexOf('あい', 3)).toEqual(3);
-          expect('abcあい'.lastIndexOf('あい', 2)).toEqual(-1);
+          expect('abcあい'.lastIndexOf('あい')).toBe(3);
+          expect('abcあい'.lastIndexOf('あい', 3)).toBe(3);
+          expect('abcあい'.lastIndexOf('あい', 2)).toBe(-1);
       });
     });
 });

-- 
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