Skip to content

Commit

Permalink
fix diff output for String objects; closes #2496
Browse files Browse the repository at this point in the history
- rename some exported functions/vars as to use locally
- update JSDoc comments
  • Loading branch information
boneskull committed Sep 22, 2016
1 parent 96e20df commit aea24cb
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 20 deletions.
45 changes: 25 additions & 20 deletions lib/utils.js
Expand Up @@ -89,7 +89,7 @@ exports.map = function(arr, fn, scope) {
* @param {number} start
* @return {number}
*/
exports.indexOf = function(arr, obj, start) {
var indexOf = exports.indexOf = function(arr, obj, start) {
for (var i = start || 0, l = arr.length; i < l; i++) {
if (arr[i] === obj) {
return i;
Expand Down Expand Up @@ -366,13 +366,11 @@ exports.highlightTags = function(name) {
*
* @api private
* @param {*} value The value to inspect.
* @param {string} [type] The type of the value, if known.
* @param {string} typeHint The type of the value
* @returns {string}
*/
function emptyRepresentation(value, type) {
type = type || exports.type(value);

switch (type) {
function emptyRepresentation(value, typeHint) {
switch (typeHint) {
case 'function':
return '[Function]';
case 'object':
Expand All @@ -391,7 +389,7 @@ function emptyRepresentation(value, type) {
* @api private
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString
* @param {*} value The value to test.
* @returns {string}
* @returns {string} Computed type
* @example
* type({}) // 'object'
* type([]) // 'array'
Expand All @@ -403,18 +401,24 @@ function emptyRepresentation(value, type) {
* type(/foo/) // 'regexp'
* type('type') // 'string'
* type(global) // 'global'
* type(new String('foo') // 'object'
*/
exports.type = function type(value) {
var type = exports.type = function type(value) {
if (value === undefined) {
return 'undefined';
} else if (value === null) {
return 'null';
} else if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {
return 'buffer';
}
return Object.prototype.toString.call(value)
var toStringType = Object.prototype.toString.call(value)
.replace(/^\[.+\s(.+?)\]$/, '$1')
.toLowerCase();
// special case for string created with String constructor;
// it's an Object on purpose and should be displayed as such
return toStringType === 'string' && typeof value === 'object'
? 'object'
: toStringType;
};

/**
Expand All @@ -433,10 +437,10 @@ exports.type = function type(value) {
* @return {string}
*/
exports.stringify = function(value) {
var type = exports.type(value);
var typeHint = type(value);

if (!~exports.indexOf(['object', 'array', 'function'], type)) {
if (type !== 'buffer') {
if (!~indexOf(['object', 'array', 'function'], typeHint)) {
if (typeHint !== 'buffer') {
return jsonStringify(value);
}
var json = value.toJSON();
Expand All @@ -447,11 +451,11 @@ exports.stringify = function(value) {

for (var prop in value) {
if (Object.prototype.hasOwnProperty.call(value, prop)) {
return jsonStringify(exports.canonicalize(value), 2).replace(/,(\n|$)/g, '$1');
return jsonStringify(exports.canonicalize(value, null, typeHint), 2).replace(/,(\n|$)/g, '$1');
}
}

return emptyRepresentation(value, type);
return emptyRepresentation(value, typeHint);
};

/**
Expand Down Expand Up @@ -480,7 +484,7 @@ function jsonStringify(object, spaces, depth) {
}

function _stringify(val) {
switch (exports.type(val)) {
switch (type(val)) {
case 'null':
case 'undefined':
val = '[' + val + ']';
Expand Down Expand Up @@ -563,14 +567,15 @@ exports.isBuffer = function(value) {
* @see {@link exports.stringify}
* @param {*} value Thing to inspect. May or may not have properties.
* @param {Array} [stack=[]] Stack of seen values
* @param {string} [typeHint] Type hint
* @return {(Object|Array|Function|string|undefined)}
*/
exports.canonicalize = function(value, stack) {
exports.canonicalize = function canonicalize(value, stack, typeHint) {
var canonicalizedObj;
/* eslint-disable no-unused-vars */
var prop;
/* eslint-enable no-unused-vars */
var type = exports.type(value);
typeHint = typeHint || type(value);
function withStack(value, fn) {
stack.push(value);
fn();
Expand All @@ -579,11 +584,11 @@ exports.canonicalize = function(value, stack) {

stack = stack || [];

if (exports.indexOf(stack, value) !== -1) {
if (indexOf(stack, value) !== -1) {
return '[Circular]';
}

switch (type) {
switch (typeHint) {
case 'undefined':
case 'buffer':
case 'null':
Expand All @@ -604,7 +609,7 @@ exports.canonicalize = function(value, stack) {
}
/* eslint-enable guard-for-in */
if (!canonicalizedObj) {
canonicalizedObj = emptyRepresentation(value, type);
canonicalizedObj = emptyRepresentation(value, typeHint);
break;
}
/* falls through */
Expand Down
4 changes: 4 additions & 0 deletions test/acceptance/utils.spec.js
Expand Up @@ -77,6 +77,10 @@ describe('lib/utils', function () {

var stringify = utils.stringify;

it('should return an object representation of a string created with a String constructor', function() {
expect(stringify(new String('foo'))).to.equal('{\n "0": "f"\n "1": "o"\n "2": "o"\n}');
});

it('should return Buffer with .toJSON representation', function() {
expect(stringify(new Buffer([0x01]))).to.equal('[\n 1\n]');
expect(stringify(new Buffer([0x01, 0x02]))).to.equal('[\n 1\n 2\n]');
Expand Down

0 comments on commit aea24cb

Please sign in to comment.