Skip to content

Commit

Permalink
fix diff output for String objects; closes #2496 (#2499)
Browse files Browse the repository at this point in the history
- rename some exported functions/vars as to use locally
- update JSDoc comments
- includes IE7/8 support
  • Loading branch information
boneskull committed Sep 27, 2016
1 parent 8bf1f29 commit 8431cb3
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 26 deletions.
63 changes: 37 additions & 26 deletions lib/utils.js
Expand Up @@ -90,7 +90,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 All @@ -108,7 +108,7 @@ exports.indexOf = function(arr, obj, start) {
* @param {Object} val Initial value.
* @return {*}
*/
exports.reduce = function(arr, fn, val) {
var reduce = exports.reduce = function(arr, fn, val) {
var rval = val;

for (var i = 0, l = arr.length; i < l; i++) {
Expand Down Expand Up @@ -314,7 +314,7 @@ exports.trim = function(str) {
* @return {Object}
*/
exports.parseQuery = function(qs) {
return exports.reduce(qs.replace('?', '').split('&'), function(obj, pair) {
return reduce(qs.replace('?', '').split('&'), function(obj, pair) {
var i = pair.indexOf('=');
var key = pair.slice(0, i);
var val = pair.slice(++i);
Expand Down Expand Up @@ -367,13 +367,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 @@ -392,7 +390,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 @@ -404,8 +402,9 @@ 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) {
Expand Down Expand Up @@ -434,25 +433,36 @@ exports.type = function type(value) {
* @return {string}
*/
exports.stringify = function(value) {
var type = exports.type(value);
var typeHint = type(value);

if (!~indexOf(['object', 'array', 'function'], typeHint)) {
if (typeHint === 'buffer') {
var json = value.toJSON();
// Based on the toJSON result
return jsonStringify(json.data && json.type ? json.data : json, 2)
.replace(/,(\n|$)/g, '$1');
}

if (!~exports.indexOf(['object', 'array', 'function'], type)) {
if (type !== 'buffer') {
// IE7/IE8 has a bizarre String constructor; needs to be coerced
// into an array and back to obj.
if (typeHint === 'string' && typeof value === 'object') {
value = reduce(value.split(''), function(acc, char, idx) {
acc[idx] = char;
return acc;
}, {});
typeHint = 'object';
} else {
return jsonStringify(value);
}
var json = value.toJSON();
// Based on the toJSON result
return jsonStringify(json.data && json.type ? json.data : json, 2)
.replace(/,(\n|$)/g, '$1');
}

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 @@ -481,7 +491,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 @@ -564,14 +574,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 @@ -580,11 +591,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 @@ -605,7 +616,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 Expand Up @@ -750,7 +761,7 @@ exports.stackTraceFilter = function() {
return function(stack) {
stack = stack.split('\n');

stack = exports.reduce(stack, function(list, line) {
stack = reduce(stack, function(list, line) {
if (isMochaInternal(line)) {
return list;
}
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 8431cb3

Please sign in to comment.