mirror of
https://github.com/nodejs/node.git
synced 2024-11-30 07:27:22 +01:00
393 lines
11 KiB
JavaScript
393 lines
11 KiB
JavaScript
var events = require('events');
|
|
|
|
|
|
exports.print = function () {
|
|
for (var i = 0, len = arguments.length; i < len; ++i) {
|
|
process.stdout.write(String(arguments[i]));
|
|
}
|
|
};
|
|
|
|
|
|
exports.puts = function () {
|
|
for (var i = 0, len = arguments.length; i < len; ++i) {
|
|
process.stdout.write(arguments[i] + '\n');
|
|
}
|
|
};
|
|
|
|
|
|
exports.debug = function (x) {
|
|
process.binding('stdio').writeError("DEBUG: " + x + "\n");
|
|
};
|
|
|
|
|
|
var error = exports.error = function (x) {
|
|
for (var i = 0, len = arguments.length; i < len; ++i) {
|
|
process.binding('stdio').writeError(arguments[i] + '\n');
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Echos the value of a value. Trys to print the value out
|
|
* in the best way possible given the different types.
|
|
*
|
|
* @param {Object} value The object to print out
|
|
* @param {Boolean} showHidden Flag that shows hidden (not enumerable)
|
|
* properties of objects.
|
|
* @param {Number} depth Depth in which to descend in object. Default is 2.
|
|
* @param {Boolean} colors Flag to turn on ANSI escape codes to color the
|
|
* output. Default is false (no coloring).
|
|
*/
|
|
exports.inspect = function (obj, showHidden, depth, colors) {
|
|
var seen = [];
|
|
|
|
var stylize = function (str, styleType) {
|
|
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
|
|
var styles = { 'bold' : [1, 22]
|
|
, 'italic' : [3, 23]
|
|
, 'underline' : [4, 24]
|
|
, 'inverse' : [7, 27]
|
|
, 'white' : [37, 39]
|
|
, 'grey' : [90, 39]
|
|
, 'black' : [30, 39]
|
|
, 'blue' : [34, 39]
|
|
, 'cyan' : [36, 39]
|
|
, 'green' : [32, 39]
|
|
, 'magenta' : [35, 39]
|
|
, 'red' : [31, 39]
|
|
, 'yellow' : [33, 39]
|
|
};
|
|
var style = { "special": "grey"
|
|
, "number": "blue"
|
|
, "boolean": "blue"
|
|
, "undefined": "red"
|
|
, "null": "red"
|
|
, "string": "green"
|
|
, "date": "magenta"
|
|
//, "name": intentionally not styling
|
|
, "regexp": "cyan"
|
|
}[styleType];
|
|
if (style) {
|
|
return '\033[' + styles[style][0] + 'm' + str +
|
|
'\033[' + styles[style][1] + 'm';
|
|
} else {
|
|
return str;
|
|
}
|
|
};
|
|
if (! colors) {
|
|
stylize = function(str, styleType) { return str; };
|
|
}
|
|
|
|
function format(value, recurseTimes) {
|
|
// Provide a hook for user-specified inspect functions.
|
|
// Check that value is an object with an inspect function on it
|
|
if (value && typeof value.inspect === 'function' &&
|
|
// Filter out the util module, it's inspect function is special
|
|
value !== exports &&
|
|
// Also filter out any prototype objects using the circular check.
|
|
!(value.constructor && value.constructor.prototype === value)) {
|
|
return value.inspect(recurseTimes);
|
|
}
|
|
|
|
// Primitive types cannot have properties
|
|
switch (typeof value) {
|
|
case 'undefined': return stylize('undefined', 'undefined');
|
|
case 'string': return stylize(
|
|
JSON.stringify(value).replace(/'/g, "\\'")
|
|
.replace(/\\"/g, '"')
|
|
.replace(/(^"|"$)/g, "'"),
|
|
'string');
|
|
case 'number': return stylize('' + value, 'number');
|
|
case 'boolean': return stylize('' + value, 'boolean');
|
|
}
|
|
// For some reason typeof null is "object", so special case here.
|
|
if (value === null) {
|
|
return stylize('null', 'null');
|
|
}
|
|
|
|
// Look up the keys of the object.
|
|
var visible_keys = Object.keys(value);
|
|
var keys = showHidden ? Object.getOwnPropertyNames(value) : visible_keys;
|
|
|
|
// Functions without properties can be shortcutted.
|
|
if (typeof value === 'function' && keys.length === 0) {
|
|
if (isRegExp(value)) {
|
|
return stylize('' + value, 'regexp');
|
|
} else {
|
|
return stylize('[Function'+ (value.name ? ': '+ value.name : '')+ ']', 'special');
|
|
}
|
|
}
|
|
|
|
// Dates without properties can be shortcutted
|
|
if (isDate(value) && keys.length === 0) {
|
|
return stylize(value.toUTCString(), 'date');
|
|
}
|
|
|
|
var base, type, braces;
|
|
// Determine the object type
|
|
if (isArray(value)) {
|
|
type = 'Array';
|
|
braces = ["[", "]"];
|
|
} else {
|
|
type = 'Object';
|
|
braces = ["{", "}"];
|
|
}
|
|
|
|
// Make functions say that they are functions
|
|
if (typeof value === 'function') {
|
|
base = (isRegExp(value)) ? ' ' + value : ' [Function'+ (value.name ? ': '+ value.name : '')+ ']';
|
|
} else {
|
|
base = "";
|
|
}
|
|
|
|
// Make dates with properties first say the date
|
|
if (isDate(value)) {
|
|
base = ' ' + value.toUTCString();
|
|
}
|
|
|
|
if (keys.length === 0) {
|
|
return braces[0] + base + braces[1];
|
|
}
|
|
|
|
if (recurseTimes < 0) {
|
|
if (isRegExp(value)) {
|
|
return stylize('' + value, "regexp");
|
|
} else {
|
|
return stylize("[Object]", "special");
|
|
}
|
|
}
|
|
|
|
seen.push(value);
|
|
|
|
var output = keys.map(function (key) {
|
|
var name, str;
|
|
if (value.__lookupGetter__) {
|
|
if (value.__lookupGetter__(key)) {
|
|
if (value.__lookupSetter__(key)) {
|
|
str = stylize("[Getter/Setter]", "special");
|
|
} else {
|
|
str = stylize("[Getter]", "special");
|
|
}
|
|
} else {
|
|
if (value.__lookupSetter__(key)) {
|
|
str = stylize("[Setter]", "special");
|
|
}
|
|
}
|
|
}
|
|
if (visible_keys.indexOf(key) < 0) {
|
|
name = "[" + key + "]";
|
|
}
|
|
if (!str) {
|
|
if (seen.indexOf(value[key]) < 0) {
|
|
if ( recurseTimes === null) {
|
|
str = format(value[key]);
|
|
} else {
|
|
str = format(value[key], recurseTimes - 1);
|
|
}
|
|
if (str.indexOf('\n') > -1) {
|
|
if (isArray(value)) {
|
|
str = str.split('\n').map(function(line) {
|
|
return ' ' + line;
|
|
}).join('\n').substr(2);
|
|
} else {
|
|
str = '\n' + str.split('\n').map(function(line) {
|
|
return ' ' + line;
|
|
}).join('\n');
|
|
}
|
|
}
|
|
} else {
|
|
str = stylize('[Circular]', 'special');
|
|
}
|
|
}
|
|
if (typeof name === 'undefined') {
|
|
if (type === 'Array' && key.match(/^\d+$/)) {
|
|
return str;
|
|
}
|
|
name = JSON.stringify('' + key);
|
|
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
|
|
name = name.substr(1, name.length-2);
|
|
name = stylize(name, "name");
|
|
} else {
|
|
name = name.replace(/'/g, "\\'")
|
|
.replace(/\\"/g, '"')
|
|
.replace(/(^"|"$)/g, "'");
|
|
name = stylize(name, "string");
|
|
}
|
|
}
|
|
|
|
return name + ": " + str;
|
|
});
|
|
|
|
seen.pop();
|
|
|
|
var numLinesEst = 0;
|
|
var length = output.reduce(function(prev, cur) {
|
|
numLinesEst++;
|
|
if( cur.indexOf('\n') >= 0 ) {
|
|
numLinesEst++;
|
|
}
|
|
return prev + cur.length + 1;
|
|
},0);
|
|
|
|
if (length > (require('readline').columns || 50)) {
|
|
output = braces[0]
|
|
+ (base === '' ? '' : base + '\n ')
|
|
+ ' '
|
|
+ output.join(',\n ')
|
|
+ ' '
|
|
+ braces[1]
|
|
;
|
|
} else {
|
|
output = braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
|
|
}
|
|
|
|
return output;
|
|
}
|
|
return format(obj, (typeof depth === 'undefined' ? 2 : depth));
|
|
};
|
|
|
|
|
|
function isArray (ar) {
|
|
return ar instanceof Array
|
|
|| Array.isArray(ar)
|
|
|| (ar && ar !== Object.prototype && isArray(ar.__proto__));
|
|
}
|
|
|
|
|
|
function isRegExp (re) {
|
|
var s = ""+re;
|
|
return re instanceof RegExp // easy case
|
|
|| typeof(re) === "function" // duck-type for context-switching evalcx case
|
|
&& re.constructor.name === "RegExp"
|
|
&& re.compile
|
|
&& re.test
|
|
&& re.exec
|
|
&& s.match(/^\/.*\/[gim]{0,3}$/);
|
|
}
|
|
|
|
|
|
function isDate (d) {
|
|
if (d instanceof Date) return true;
|
|
if (typeof d !== "object") return false;
|
|
var properties = Date.prototype && Object.getOwnPropertyNames(Date.prototype);
|
|
var proto = d.__proto__ && Object.getOwnPropertyNames(d.__proto__);
|
|
return JSON.stringify(proto) === JSON.stringify(properties);
|
|
}
|
|
|
|
|
|
var pWarning;
|
|
|
|
exports.p = function () {
|
|
if (!pWarning) {
|
|
pWarning = "util.p will be removed in future versions of Node. Use util.puts(util.inspect()) instead.\n";
|
|
exports.error(pWarning);
|
|
}
|
|
for (var i = 0, len = arguments.length; i < len; ++i) {
|
|
error(exports.inspect(arguments[i]));
|
|
}
|
|
};
|
|
|
|
|
|
function pad (n) {
|
|
return n < 10 ? '0' + n.toString(10) : n.toString(10);
|
|
}
|
|
|
|
|
|
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
|
|
// 26 Feb 16:19:34
|
|
function timestamp () {
|
|
var d = new Date();
|
|
return [ d.getDate()
|
|
, months[d.getMonth()]
|
|
, [pad(d.getHours()), pad(d.getMinutes()), pad(d.getSeconds())].join(':')
|
|
].join(' ');
|
|
}
|
|
|
|
|
|
exports.log = function (msg) {
|
|
exports.puts(timestamp() + ' - ' + msg.toString());
|
|
};
|
|
|
|
|
|
var execWarning;
|
|
exports.exec = function () {
|
|
if (!execWarning) {
|
|
execWarning = 'util.exec has moved to the "child_process" module. Please update your source code.';
|
|
error(execWarning);
|
|
}
|
|
return require('child_process').exec.apply(this, arguments);
|
|
};
|
|
|
|
|
|
exports.pump = function (readStream, writeStream, callback) {
|
|
var callbackCalled = false;
|
|
|
|
function call (a, b, c) {
|
|
if (callback && !callbackCalled) {
|
|
callback(a, b, c);
|
|
callbackCalled = true;
|
|
}
|
|
}
|
|
|
|
if (!readStream.pause) readStream.pause = function () {readStream.emit("pause");};
|
|
if (!readStream.resume) readStream.resume = function () {readStream.emit("resume");};
|
|
|
|
readStream.addListener("data", function (chunk) {
|
|
if (writeStream.write(chunk) === false) readStream.pause();
|
|
});
|
|
|
|
writeStream.addListener("pause", function () {
|
|
readStream.pause();
|
|
});
|
|
|
|
writeStream.addListener("drain", function () {
|
|
readStream.resume();
|
|
});
|
|
|
|
writeStream.addListener("resume", function () {
|
|
readStream.resume();
|
|
});
|
|
|
|
readStream.addListener("end", function () {
|
|
writeStream.end();
|
|
});
|
|
|
|
readStream.addListener("close", function () {
|
|
call();
|
|
});
|
|
|
|
readStream.addListener("error", function (err) {
|
|
writeStream.end();
|
|
call(err);
|
|
});
|
|
|
|
writeStream.addListener("error", function (err) {
|
|
readStream.destroy();
|
|
call(err);
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Inherit the prototype methods from one constructor into another.
|
|
*
|
|
* The Function.prototype.inherits from lang.js rewritten as a standalone
|
|
* function (not on Function.prototype). NOTE: If this file is to be loaded
|
|
* during bootstrapping this function needs to be revritten using some native
|
|
* functions as prototype setup using normal JavaScript does not work as
|
|
* expected during bootstrapping (see mirror.js in r114903).
|
|
*
|
|
* @param {function} ctor Constructor function which needs to inherit the
|
|
* prototype
|
|
* @param {function} superCtor Constructor function to inherit prototype from
|
|
*/
|
|
exports.inherits = function (ctor, superCtor) {
|
|
ctor.super_ = superCtor;
|
|
ctor.prototype = Object.create(superCtor.prototype, {
|
|
constructor: {
|
|
value: ctor,
|
|
enumerable: false
|
|
}
|
|
});
|
|
};
|