Skip to content

Commit

Permalink
Fixes for eval, sourcemaps (#25)
Browse files Browse the repository at this point in the history
* Don't fail on empty file component of a stack trace
* Capture source of eval
* Don't break sourcemaps
* Clean things up a bit, get more organized
  • Loading branch information
myndzi committed Feb 17, 2018
1 parent e928b98 commit 4ceaf52
Show file tree
Hide file tree
Showing 12 changed files with 98 additions and 37 deletions.
15 changes: 3 additions & 12 deletions .gitignore
@@ -1,12 +1,3 @@
*
!.gitignore
!package.json
!index.js
!kitchensink.js
!clustertest.js
!test.js
!test-promisify.js
!README.md
!key.pem
!key-cert.pem
!proxy.js
/node_modules
/tests/test-sourcemaps.js
/tests/test-sourcemaps.js.map
42 changes: 24 additions & 18 deletions index.js
Expand Up @@ -36,14 +36,23 @@ function setPrototypeOf(obj, proto) {

// hook stuff
(function () {
var _Error_prepareStackTrace = Error.prepareStackTrace;
var hooked = function (_, stack) { return stack; };

function getStack() {
Error.prepareStackTrace = hooked
var _Error_prepareStackTrace = Error.prepareStackTrace;
Error.prepareStackTrace = hooked;
var err = new Error();
var stack = err.stack.map(function (item) {
if (item.isEval()) {
var matched = item.getEvalOrigin().match(/\((.*):(\d*):(\d*)\)/) || {};
return {
name: '<eval>',
file: matched[1],
line: matched[2]
};
}
return {
name: item.getFunctionName(),
file: item.getFileName(),
line: item.getLineNumber()
};
Expand All @@ -55,11 +64,13 @@ function setPrototypeOf(obj, proto) {
function findCallsite(stack) {
for (var i = 0; i < stack.length; i++) {
// Ignore frames from:
// - null/undefined values
// - wtfnode by excluding __filename
// - builtins by excluding files with no path separator
// - internal builtins by excluding files beginning with 'internal/'
// (even on windows, the stack trace uses unix separators for these)
if (stack[i].file !== __filename &&
if (stack[i].file &&
stack[i].file !== __filename &&
stack[i].file.indexOf(path.sep) !== -1 &&
stack[i].file.slice(0, 9) !== 'internal/'
) {
Expand Down Expand Up @@ -112,6 +123,7 @@ function setPrototypeOf(obj, proto) {
var stack = getStack();

// this should inherit 'name' and 'length' and any other properties that have been assigned
// also inherits prototype, and symbols like the promisify value!
copyProperties(fn, wrapped);

// we use these later to identify the source information about an open handle
Expand Down Expand Up @@ -310,11 +322,11 @@ function formatTime(t) {
var count = 0;
function getCallsite(thing) {
if (!thing.__callSite) {
var name = ((thing.name ? thing.name : thing.constructor.name) || 'unknown').trim();
var name = ((thing.name ? thing.name : thing.constructor.name) || '(anonymous)').trim();
if (!DONT_INSTRUMENT[name]) {
console.warn('Unable to determine callsite for "'+name+'". Did you require `wtfnode` at the top of your entry point?');
}
return { file: 'unknown', line: 0 };
return { name: '(anonymous)', file: 'unknown', line: 0 };
}
return thing.__callSite;
};
Expand Down Expand Up @@ -359,7 +371,7 @@ function dump() {
console.log(' - Listeners:');
keypressListeners.forEach(function (fn) {
var callSite = getCallsite(fn);
console.log(' - %s: %s @ %s:%d', 'keypress', fn.name || '(anonymous)', callSite.file, callSite.line);
console.log(' - %s: %s @ %s:%d', 'keypress', fn.name || fn.__name || callSite.name || '(anonymous)', callSite.file, callSite.line);
});
}
});
Expand Down Expand Up @@ -425,7 +437,7 @@ function dump() {
console.log(' - Listeners:');
connectListeners.forEach(function (fn) {
var callSite = getCallsite(fn);
console.log(' - %s: %s @ %s:%d', 'connect', fn.name || '(anonymous)', callSite.file, callSite.line);
console.log(' - %s: %s @ %s:%d', 'connect', fn.name || fn.__name || callSite.name || '(anonymous)', callSite.file, callSite.line);
});
}
});
Expand Down Expand Up @@ -470,7 +482,7 @@ function dump() {
console.log(' - Listeners:');
listeners.forEach(function (fn) {
var callSite = getCallsite(fn);
console.log(' - %s: %s @ %s:%d', eventType, fn.__name || fn.name || '(anonymous)', callSite.file, callSite.line);
console.log(' - %s: %s @ %s:%d', eventType, fn.name || fn.__name || callSite.name || '(anonymous)', callSite.file, callSite.line);
});
}
});
Expand Down Expand Up @@ -522,11 +534,8 @@ function dump() {
timers.forEach(function (t) {
var fn = t[timerCallback(t)],
callSite = getCallsite(fn);
if (fn.__name) {
console.log(' - (%d ~ %s) %s @ %s:%d', t._idleTimeout, formatTime(t._idleTimeout), fn.__name, callSite.file, callSite.line);
} else {
console.log(' - (%d ~ %s) %s @ %s:%d', t._idleTimeout, formatTime(t._idleTimeout), fn.name, callSite.file, callSite.line);
}

console.log(' - (%d ~ %s) %s @ %s:%d', t._idleTimeout, formatTime(t._idleTimeout), fn.name || fn.__name || callSite.name || '(anonymous)', callSite.file, callSite.line);
});
}

Expand All @@ -536,11 +545,8 @@ function dump() {
intervals.forEach(function (t) {
var fn = t[timerCallback(t)],
callSite = getCallsite(fn);
if (fn.__name) {
console.log(' - (%d ~ %s) %s @ %s:%d', t._idleTimeout, formatTime(t._idleTimeout), fn.__name, callSite.file, callSite.line);
} else {
console.log(' - (%d ~ %s) %s @ %s:%d', t._idleTimeout, formatTime(t._idleTimeout), fn.name, callSite.file, callSite.line);
}

console.log(' - (%d ~ %s) %s @ %s:%d', t._idleTimeout, formatTime(t._idleTimeout), fn.name || fn.__name || callSite.name, callSite.file, callSite.line);
});
}

Expand Down
17 changes: 14 additions & 3 deletions package.json
@@ -1,18 +1,29 @@
{
"name": "wtfnode",
"version": "0.5.7",
"version": "0.6.0",
"description": "Utility to help find out why Node isn't exiting",
"repository": {
"type": "git",
"url": "https://github.com/myndzi/wtfnode"
},
"main": "index.js",
"files": [
"index.js",
"proxy.js",
"README.md"
],
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "(cd tests && node test && node test-eval && node test-promisify)",
"test-sourcemaps": "(cd tests && coffee --map --compile test-sourcemaps.coffee && node test-sourcemaps.js || exit 0)",
"kitchensink": "(cd tests && node kitchensink)"
},
"author": "Kris Reeves",
"bin": {
"wtfnode": "proxy.js"
},
"license": "ISC"
"license": "ISC",
"devDependencies": {
"coffee-script": "^1.12.7",
"source-map-support": "^0.5.3"
}
}
32 changes: 32 additions & 0 deletions test-all.sh
@@ -0,0 +1,32 @@
#!/bin/bash -e

. ~/.nvm/nvm.sh

CURRENT_VERSION="$(node --version)"

declare -a versions=(
"0.10"
"0.12"
"4"
"5"
"6"
"7"
"8"
"9"
)

test_version () {
nvm install "$1" >/dev/null 2>/dev/null
nvm use "$1" >/dev/null
npm test >/dev/null
}

for ver in "${versions[@]}"; do
if test_version "$ver"; then
echo "$ver: ok"
else
echo "$ver: failed"
fi
done

nvm use "$CURRENT_VERSION"
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion kitchensink.js → tests/kitchensink.js
@@ -1,4 +1,4 @@
var wtf = require('./index');
var wtf = require('../index');

var assert = require('assert');
cp = require('child_process'),
Expand Down
2 changes: 1 addition & 1 deletion clustertest.js → tests/test-cluster.js
@@ -1,6 +1,6 @@
'use strict';

var wtf = require('./index'),
var wtf = require('../index'),
cluster = require('cluster');

if (cluster.isMaster) {
Expand Down
7 changes: 7 additions & 0 deletions tests/test-eval.js
@@ -0,0 +1,7 @@
'use strict';

var wtf = require('../index');

var foo = new Function('setTimeout(function evaled() {}, 100);');
foo();
wtf.dump();
2 changes: 1 addition & 1 deletion test-promisify.js → tests/test-promisify.js
@@ -1,6 +1,6 @@
'use strict';

var wtf = require('./index'),
var wtf = require('../index'),
util = require('util');

if (util.promisify) {
Expand Down
14 changes: 14 additions & 0 deletions tests/test-sourcemaps.coffee
@@ -0,0 +1,14 @@
wtf = require('../index')
require('source-map-support').install()

noop = () ->
undefined

setTimeout(noop, 1000)

wtf.dump()

foo = ->
bar = -> throw new Error 'this is a demo'
bar()
foo()
2 changes: 1 addition & 1 deletion test.js → tests/test.js
@@ -1,6 +1,6 @@
'use strict';

var wtf = require('./index');
var wtf = require('../index');

var EventEmitter = require('events').EventEmitter,
assert = require('assert');
Expand Down

0 comments on commit 4ceaf52

Please sign in to comment.