atom-nuclide
Version:
A unified developer experience for web and mobile development, built as a suite of features on top of Atom to provide hackability and the support of an active community.
151 lines (112 loc) • 4.13 kB
JavaScript
// This function will be injected into the target process.
module.exports = function injection(require, debug, options) {
var consoleIsWrapped = false,
nextMessageId = 0,
messagesCache = {};
var makeMirror = debug.get('MakeMirror');
function ConsoleMessage(fn, wrapper, args) {
var location = getCallerFuncLocation(wrapper);
this.id = nextMessageId++;
this.source = 'console-api';
this.level = getLevel(fn);
this.type = this.level == 'log' ? fn : undefined;
this.line = location.line;
this.column = location.column;
this.url = location.url;
this.repeatCount = 0;
this.timestamp = Date.now();
this.parameters = args;
}
function getLevel(fn) {
return ['warning', 'error', 'debug', 'log'].indexOf(fn) > -1 ? fn : 'log';
}
function getCallerFuncLocation(wrapper) {
var oldPrepareStackTrace = Error.prepareStackTrace,
error = new Error(),
callerFrame;
Error.prepareStackTrace = function(error, stack) { return stack; };
Error.captureStackTrace(error, wrapper);
callerFrame = error.stack[0];
Error.prepareStackTrace = oldPrepareStackTrace;
var fileName = callerFrame.getFileName();
fileName = debug.convert.v8NameToInspectorUrl(fileName);
var url = fileName || callerFrame.getEvalOrigin();
return {
url: url,
line: callerFrame.getLineNumber(),
column: callerFrame.getColumnNumber()
};
}
function clearMessages() {
messagesCache = {};
}
function wrapConsole() {
if (consoleIsWrapped) return;
var specials = ['assert'];
Object.keys(console).forEach(function(fn) {
if (/^_/.test(fn)) return;
if (specials.indexOf(fn) > -1) return;
console['_'+fn] = console[fn];
console[fn] = wrapFunction(fn, console[fn]);
});
console.assert = wrapAssertFunction('assert', console.assert);
consoleIsWrapped = true;
}
function unwrapConsole() {
if (!consoleIsWrapped) return;
clearMessages();
Object.keys(console).forEach(function(fn) {
if (!/^_/.test(fn)) {
console[fn] = console['_' + fn];
delete console['_' + fn];
}
});
consoleIsWrapped = false;
}
function wrapFunction(fn, func) {
return function WRAPPED_BY_NODE_INSPECTOR() {
var args = [];
Array.prototype.push.apply(args, arguments);
sendMessageToInspector(fn, WRAPPED_BY_NODE_INSPECTOR, args);
return func.apply(console, args);
};
}
function wrapAssertFunction(fn, func) {
return function wrapper(condition) {
var args = [];
Array.prototype.push.apply(args, arguments);
if (!condition)
sendMessageToInspector(fn, wrapper, args);
return func.apply(console, args);
};
}
function sendMessageToInspector(fn, wrapper, args) {
var message = new ConsoleMessage(fn, wrapper, args);
var cache = messagesCache[message.id] = {};
message.parameters = message.parameters.map(function(arg) {
return debug.serializeAndCacheMirror(cache, makeMirror(arg));
});
debug.command('Console.messageAdded', { message: message });
}
debug.register('Console.messageAdded', debug.commandToEvent);
debug.register('Console.messagesCleared', debug.commandToEvent);
debug.register('Console.messageRepeatCountUpdated', debug.commandToEvent);
debug.register('Console.clearMessages', function(request, response) {
clearMessages();
debug.command('Console.messagesCleared');
});
debug.register('Console._lookupConsoleId', function(request, response) {
var messageId = request.arguments.messageId;
var objectId = request.arguments.objectId;
var cache = messagesCache[messageId];
if (!cache)
return response.failed('Console message #' + messageId + '# not found');
var mirror = cache[objectId];
if (!mirror)
return response.failed('Object #' + objectId + '# not found');
//serialize body and append serialized refs to response
response.body = debug.serializeAndCacheMirror(cache, mirror, response);
});
debug.on('close', unwrapConsole);
wrapConsole();
};