-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
89 lines (69 loc) · 2.36 KB
/
index.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
'use strict';
function STORE(container, target, fallback) {
const store = container.get(target) || fallback || new Map();
container.set(target, store);
return store;
}
function QUEUE(container, target, pair) {
const store = STORE(container, target);
const queue = STORE(store, pair, []);
return queue;
}
function PAIR(container, target) {
const store = STORE(container, target);
return function (event, error) {
const EVENT = STORE(store, event);
const ERROR = STORE(EVENT, error, [event, error]);
return ERROR;
}
}
function instantiate(queuing) {
queuing = queuing || false;
const pairs = new Map();
const queues = new Map();
const cleanups = new WeakMap();
const cleanup = promise => cleanups.get(promise);
const call = Function.call.call.bind(Function.call);
const clean = promise => (promise && cleanup(promise).map(call), promise);
const on = Function.bind.apply(function(target, event, error) {
const pair = PAIR(pairs, target)(event, error);
const once = Function.call.bind(on.once, target);
const off = Function.call.bind(on.off, target);
const next = $ => {
const clean = $ => actions.map(call);
const actions = [];
const promise = new Promise((resolve, reject) => {
const onevent = $ => (keep(event), clean(), resolve($));
once(event, onevent);
actions.push($ => off(event, onevent));
if (error == null) return;
const onerror = $ => (keep(error), clean(), reject($));
once(error, onerror);
actions.push($ => off(error, onerror));
});
cleanups.set(promise, actions);
return promise;
};
const pick = $ => clean(queue.shift());
const keep = $ => queuing && queue.push(next());
const queue = QUEUE(queues, target, pair);
if (queue.length) return queuing ? pick() : queue[0];
if (queuing) return next();
const promise = next();
queue.push(promise);
cleanup(promise).push(pick);
return promise;
}, arguments);
on.clean = function() {
callbacks.values.map(call);
};
on.queue = function() {
const args = Array.prototype.concat.apply([true], arguments);
return instantiate.apply(null, args);
};
on.instantiate = instantiate;
on.once = require('events').prototype.once;
on.off = require('events').prototype.removeListener;
return on;
}
module.exports = instantiate();