function canonicalize(value, stack) {
  var canonicalizedObj,
    withStack = function withStack(value, fn) {
      stack.push(value);
      fn();
      stack.pop();
    };

  stack = stack || [];

  if (~stack.indexOf(value)) return '[Circular]';
  switch(type(value)) {
    case 'undefined':
    case 'buffer':
    case 'null':
      canonicalizedObj = value;
      break;
    case 'array':
      withStack(value, function () {
        canonicalizedObj = value.map(function (item) {
          return canonicalize(item, stack);
        });
      });
      break;
    case 'function':
      canonicalizedObj = '[Function]';
      break;
    case 'global':
      canonicalizedObj = '[object global]';
      break;
    case 'object':
      canonicalizedObj = canonicalizedObj || {};
      withStack(value, function () {
        keys(value).sort().forEach(function (key) {
          canonicalizedObj[key] = canonicalize(value[key], stack);
        });
      });
      break;
    case 'date':
    case 'number':
    case 'regexp':
    case 'boolean':
      canonicalizedObj = value;
      break;
    default:
      canonicalizedObj = value.toString();
  }

  return canonicalizedObj;
}
/**
 * @summary Return a new Thing that has the keys in sorted order. Recursively.
 * @description
 * - has already been seen, return string `'[Circular]'`
 * - is `undefined`, return string `'[undefined]'`
 * - is `null`, return value `'[null]'`
 * - is some other primitive, return the value
 * - is not a primitive or an `Array`, `Object`, or `Function`, return the value of the Thing's `toString()` method
 * - is a non-empty `Array`, `Object`, or `Function`, return the result of calling this function again.
 * - is an empty `Array`, `Object`, or `Function`, return the result of calling `emptyRepresentation()`
 *
 * @param {*} value Thing to inspect.  May or may not have properties.
 * @param {Array} [stack=[]] Stack of seen values
 * @return {(Object|Array|Function|string|undefined)}
 * @see {@link exports.stringify}
 * @api private
 */
@summary Return a new Thing that has the keys in sorted order. Recursively.

@param {*} value Thing to inspect.  May or may not have properties.
@summary Return a new Thing that has the keys in sorted order . Recursively . @param { * } value Thing to inspect . May or may not have properties .
function canonicalize(value, stack) {
  var canonicalizedObj,
    withStack = function withStack(value, fn) {
      stack.push(value);
      fn();
      stack.pop();
    };
  stack = stack || [];
  if (~stack.indexOf(value)) return '[Circular]';
  switch(type(value)) {
    case 'undefined':
    case 'buffer':
    case 'null':
      canonicalizedObj = value;
      break;
    case 'array':
      withStack(value, function () {
        canonicalizedObj = value.map(function (item) {
          return canonicalize(item, stack);
        });
      });
      break;
    case 'function':
      canonicalizedObj = '[Function]';
      break;
    case 'global':
      canonicalizedObj = '[object global]';
      break;
    case 'object':
      canonicalizedObj = canonicalizedObj || {};
      withStack(value, function () {
        keys(value).sort().forEach(function (key) {
          canonicalizedObj[key] = canonicalize(value[key], stack);
        });
      });
      break;
    case 'date':
    case 'number':
    case 'regexp':
    case 'boolean':
      canonicalizedObj = value;
      break;
    default:
      canonicalizedObj = value.toString();
  }
  return canonicalizedObj;
}
function canonicalize ( value , stack ) { var canonicalizedObj , withStack = function withStack ( value , fn ) { stack . push ( value ) ; fn ( ) ; stack . pop ( ) ; } ; stack = stack || [ ] ; if ( ~ stack . indexOf ( value ) ) return '[Circular]' ; switch ( type ( value ) ) { case 'undefined' : case 'buffer' : case 'null' : canonicalizedObj = value ; break ; case 'array' : withStack ( value , function ( ) { canonicalizedObj = value . map ( function ( item ) { return canonicalize ( item , stack ) ; } ) ; } ) ; break ; case 'function' : canonicalizedObj = '[Function]' ; break ; case 'global' : canonicalizedObj = '[object global]' ; break ; case 'object' : canonicalizedObj = canonicalizedObj || { } ; withStack ( value , function ( ) { keys ( value ) . sort ( ) . forEach ( function ( key ) { canonicalizedObj [ key ] = canonicalize ( value [ key ] , stack ) ; } ) ; } ) ; break ; case 'date' : case 'number' : case 'regexp' : case 'boolean' : canonicalizedObj = value ; break ; default : canonicalizedObj = value . toString ( ) ; } return canonicalizedObj ; }
@summary Return a new Thing that has the keys in sorted order.
@summary Return a new Thing that has the keys in sorted order .