blob: 77b08168e5f5448aaa10ef393fede2229b88ee4a [file] [log] [blame]
'use strict';
module.exports = function (object, filterFn) {
return cleanYamlObj(object, filterFn || defaultFilter, true, []);
};
function cleanYamlObj(object, filter, isRoot, seen) {
if (object === undefined) {
return null;
}
if (typeof object === 'function') {
return object.toString();
}
if (Buffer.isBuffer(object)) {
return 'Buffer\n' + object.toString('hex').split('')
.reduce(function (set, c) {
if (set.length && set[set.length - 1].length === 1) {
set[set.length - 1] += c;
if (set.length && set.length % 20 === 0) {
set[set.length - 1] += '\n';
} else {
set[set.length - 1] += ' ';
}
} else {
set.push(c);
}
return set;
}, []).join('').trim();
}
if (object && typeof object === 'object') {
if (object instanceof RegExp) {
return object.toString();
}
seen = seen.concat([object]);
var isArray = Array.isArray(object);
// Fill in any holes. This means we lose expandos,
// but we were gonna lose those anyway.
if (isArray) {
object = Array.apply(null, object);
}
var isError = object && typeof object === 'object' && object instanceof Error;
var set = isArray ? [] : {};
// name is typically not an ownProperty on an Error
if (isError && object.name && !object.hasOwnProperty('name') && filter('name', isRoot, object, set)) {
setProp('name', object, set, seen, filter);
}
var keys = Object.getOwnPropertyNames(object);
return keys.reduce(function (set, k) {
// magic property!
if (isArray && k === 'length') {
return set;
}
// Don't dump massive EventEmitter and Domain
// objects onto the output, that's never friendly.
if (isError && /^domain/.test(k)) {
return set;
}
if (!filter(k, isRoot, object, set)) {
return set;
}
setProp(k, object, set, seen, filter);
return set;
}, set);
}
return object;
}
function setProp(propName, source, target, seen, filter) {
if (seen.indexOf(source[propName]) === -1) {
target[propName] = cleanYamlObj(source[propName], filter, false, seen);
} else {
target[propName] = '[Circular]';
}
}
function defaultFilter() {
return true;
}