--- /dev/null
+'use strict';
+
+var strCompare = require('../string/#/case-insensitive-compare')
+ , isObject = require('./is-object')
+
+ , resolve, typeMap;
+
+typeMap = {
+ undefined: 0,
+ object: 1,
+ boolean: 2,
+ string: 3,
+ number: 4
+};
+
+resolve = function (a) {
+ if (isObject(a)) {
+ if (typeof a.valueOf !== 'function') return NaN;
+ a = a.valueOf();
+ if (isObject(a)) {
+ if (typeof a.toString !== 'function') return NaN;
+ a = a.toString();
+ if (typeof a !== 'string') return NaN;
+ }
+ }
+ return a;
+};
+
+module.exports = function (a, b) {
+ if (a === b) return 0; // Same
+
+ a = resolve(a);
+ b = resolve(b);
+ if (a == b) return typeMap[typeof a] - typeMap[typeof b]; //jslint: ignore
+ if (a == null) return -1;
+ if (b == null) return 1;
+ if ((typeof a === 'string') || (typeof b === 'string')) {
+ return strCompare.call(a, b);
+ }
+ if ((a !== a) && (b !== b)) return 0; //jslint: ignore
+ return Number(a) - Number(b);
+};