-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtrace.js
88 lines (73 loc) · 2.19 KB
/
trace.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
87
88
'use strict';
const chain = require('stack-chain');
const asyncHook = require('async_hooks');
// Contains the call site objects of all the previous ticks leading
// up to this one
const stack = [null];
const traces = new Map();
//
// Manipulate stack trace
//
// add lastTrace to the callSite array
chain.filter.attach(function (error, frames) {
return frames.filter(function (callSite) {
const name = callSite && callSite.getFileName();
return (!name || name !== 'async_hooks.js');
});
});
chain.extend.attach(function (error, frames) {
const lastTrace = stack[stack.length - 1];
frames.push.apply(frames, lastTrace);
return frames;
});
//
// Track handle objects
//
const hooks = asyncHook.createHook({
init: asyncInit,
before: asyncBefore,
after: asyncAfter,
destroy: asyncDestroy
});
hooks.enable();
function getCallSites(skip) {
const limit = Error.stackTraceLimit;
Error.stackTraceLimit = limit + skip;
const stack = chain.callSite({
extend: false,
filter: true,
slice: skip
});
Error.stackTraceLimit = limit;
return stack;
}
function asyncInit(id, type, triggerId, resource) {
const trace = getCallSites(2);
// Add all the callSites from previous ticks
if (triggerId !== 0) {
trace.push.apply(trace, traces.get(triggerId));
}
// Cut the trace so it don't contain callSites there won't be shown anyway
// because of Error.stackTraceLimit
trace.splice(Error.stackTraceLimit);
// `trace` now contains callSites from this ticks and all the ticks leading
// up to this event in time
traces.set(id, trace);
}
function asyncBefore(id) {
// push the associated trace to the stack for this specific async action,
// thereby allowing it to become a part of a error `stack` string.
stack.push(traces.get(id));
}
function asyncAfter(id) {
// remove the associated on the stack.
// In some cases the such the handle context is lost. So this prevents the
// callSites leaking into the wrong stack trace.
// In other cases MakeCallback is called synchronously, this causes there
// to be more than one push on the stack. So this also recover the relevant
// stack for the parent.
stack.pop();
}
function asyncDestroy(id) {
traces.delete(id);
}