-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathhook.js
86 lines (64 loc) · 1.77 KB
/
hook.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
const asyncHooks = require('async_hooks');
const head = array => array.length ? array[array.length - 1] : null;
let promiseData;
let contextStack;
let errorStack;
const parseStack = stack => stack.split('\n').slice(1);
const getStack = () => parseStack((new Error()).stack);
const getContext = () => contextStack.slice();
const pushErrorContext = () => errorStack.push(getContext());
const getLastErrorContext = () => head(errorStack);
function init(id, type, triggerId) {
if (type !== 'PROMISE') return;
promiseData.set(id, {
stack: getStack(),
context: getContext(),
trigger: triggerId
});
}
function before(id) {
if (!promiseData.has(id)) return;
contextStack.push(id);
}
function after(id) {
if (!promiseData.has(id)) return;
contextStack.pop();
}
function destroy(id) {
if (!promiseData.has(id)) return;
promiseData.delete(id);
}
const hook = asyncHooks.createHook({
init, before, after, destroy
});
function enable() {
hook.enable();
}
function disable() {
hook.disable();
clearData();
}
function getLongStack(err, filter = () => true) {
const errorContext = head(getLastErrorContext());
const headline = err.stack.split('\n')[0];
let longStack = parseStack(err.stack);
let nextContext = errorContext;
while (promiseData.has(nextContext)) {
let nextContextData = promiseData.get(nextContext);
longStack = longStack.concat(nextContextData.stack);
nextContext = head(nextContextData.context);
}
return headline + '\n' + longStack.filter(filter).join('\n');
}
function clearData() {
promiseData = new Map();
contextStack = [];
errorStack = [];
}
clearData();
module.exports = {
enable,
disable,
getLongStack,
pushErrorContext
};