forked from AndreasMadsen/async-hook
/
async-hook.js
103 lines (84 loc) · 2.33 KB
/
async-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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
const patchs = {
'timers': require('./patches/timers.js')
};
const uidSymbol = Symbol('async-hook-uid');
function State() {
this.enabled = false;
this.counter = 0;
}
function Hooks() {
const initFns = this.initFns = [];
const preFns = this.preFns = [];
const postFns = this.postFns = [];
const destroyFns = this.destroyFns = [];
this.init = function (uid, parent) {
this[uidSymbol] = uid;
// send the parent uid, not the parent handle. The user map the handle
// objects appropiatly if needed.
if (parent !== null) parent = parent[uidSymbol];
// call hooks
for (const hook of initFns) {
hook(uid, this, parent);
}
};
this.pre = function () {
const uid = this[uidSymbol];
// call hooks
for (const hook of preFns) {
hook(uid, this);
}
};
this.post = function () {
const uid = this[uidSymbol];
// call hooks
for (const hook of postFns) {
hook(uid, this);
}
};
this.destroy = function (uid) {
// call hooks
for (const hook of destroyFns) {
hook(uid);
}
};
}
Hooks.prototype.add = function (hooks) {
if (hooks.init) this.initFns.push(hooks.init);
if (hooks.pre) this.preFns.push(hooks.pre);
if (hooks.post) this.postFns.push(hooks.post);
if (hooks.destroy) this.destroyFns.push(hooks.destroy);
};
function removeElement(array, item) {
const index = array.indexOf(item);
if (index === -1) return;
array.splice(index, 1);
}
Hooks.prototype.remove = function (hooks) {
if (hooks.init) removeElement(this.initFns, hooks.init);
if (hooks.pre) removeElement(this.preFns, hooks.pre);
if (hooks.post) removeElement(this.postFns, hooks.post);
if (hooks.destroy) removeElement(this.destroyFns, hooks.destroy);
};
function AsyncHook() {
this._state = new State();
this._hooks = new Hooks();
// expose version for conflict detection
this.version = require('./package.json').version;
// apply patches
for (const key of Object.keys(patchs)) {
patchs[key].call(this);
}
}
module.exports = AsyncHook;
AsyncHook.prototype.addHooks = function (hooks) {
this._hooks.add(hooks);
};
AsyncHook.prototype.removeHooks = function (hooks) {
this._hooks.remove(hooks);
};
AsyncHook.prototype.enable = function () {
this._state.enabled = true;
};
AsyncHook.prototype.disable = function () {
this._state.enabled = false;
};