-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
208 lines (176 loc) · 4.47 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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
"use strict";
const {CompositeDisposable, Disposable} = require("atom");
/**
* Map-flavoured alternative to Atom's {@link CompositeDisposable} class.
*
* Geared towards Atom package developers, but compatible with any project
* that uses {@linkcode event-kit|https://npmjs.com/package/event-kit}.
*
* @class
*/
class MappedDisposable {
/**
* Create a new instance, optionally with a list of keys and disposables.
*
* @example new MappedDisposable([ [key1, disp1], [key2, disp2] ]);
* @param {*} [iterable=null]
* @constructor
*/
constructor(iterable = null){
this.disposables = new Map();
if(null !== iterable)
for(let [key, value] of iterable){
if(!(value instanceof CompositeDisposable))
value = new CompositeDisposable(value);
this.disposables.set(key, value);
}
}
/**
* Delete keys and dispose of their values.
*
* If passed no arguments, the method disposes of everything, rendering the
* MappedDisposable instance completely inert. Future method calls do nothing.
*
* @param {...*} [keys] - Keys to dispose
*/
dispose(...keys){
if(this.disposed)
return;
// If objects were provided, target the disposables specifically
if(keys.length){
for(const key of keys){
const disposable = this.disposables.get(key);
if(key && "function" === typeof key.dispose)
key.dispose();
if(disposable){
disposable.dispose();
this.disposables.delete(key);
}
}
}
// Otherwise, dispose the MappedDisposable itself
else{
this.disposed = true;
this.disposables.forEach((value, key) => {
value.dispose();
if(key && "function" === typeof key.dispose)
key.dispose();
});
this.disposables.clear();
this.disposables = null;
}
}
/**
* Add one or more disposables to a key's disposables list.
*
* @param {*} key
* @param {...*} [disposables]
*/
add(key, ...disposables){
if(this.disposed)
return;
const keyDisposables = this.disposables.get(key);
keyDisposables
? keyDisposables.add(...disposables)
: this.disposables.set(key, new CompositeDisposable(...disposables));
}
/**
* Remove one or more disposables from a key's disposables list.
*
* If no disposables are passed, the object itself is removed from the
* MappedDisposable. Any disposables keyed to it are not disposed of.
*
* @param {*} key
* @param {...*} [disposables]
*/
remove(key, ...disposables){
if(this.disposed)
return;
const disposable = this.disposables.get(key);
if(disposable){
// Remove specific disposables if any were provided
if(disposables.length){
for(const unwantedDisposable of disposables)
disposable.remove(unwantedDisposable);
}
// Otherwise, remove the keyed object itself
else this.disposables.delete(key);
}
}
/**
* Alias of {@link MappedDisposable#remove}, included for parity with {@link Map} objects.
*
* @param {*} key
* @param {...*} [disposables]
* @see {@link MappedDisposable#remove}
*/
delete(key, ...disposables){
this.remove(key, ...disposables);
}
/**
* Clear the contents of the MappedDisposable.
*
* Individual disposables are not disposed of.
*/
clear(){
if(this.disposed)
return;
this.disposables.clear();
}
/**
* Number of entries (key/disposable pairs) stored in the instance.
*
* @readonly
* @return {Number}
*/
get size(){
return this.disposed
? 0
: this.disposables.size;
}
/**
* Determine if an entry with the given key exists in the MappedDisposable.
*
* @param {*} key
* @return {Boolean}
*/
has(key){
return this.disposed
? false
: this.disposables.has(key);
}
/**
* Retrieve the disposables list keyed to an object.
*
* If the MappedDisposable has been disposed, the method returns `undefined`.
*
* @param {*} key
* @return {CompositeDisposable}
*/
get(key){
return this.disposed
? undefined
: this.disposables.get(key);
}
/**
* Replace the disposable that's keyed to an object.
*
* A {@link TypeError} is thrown if the value argument lacks a `dispose` method.
*
* @param {*} key
* @param {Disposable} value
*/
set(key, value){
if(this.disposed)
return;
if(!Disposable.isDisposable(value))
throw new TypeError("Value must have a .dispose() method");
this.disposables.set(key, value);
}
}
/**
* Whether the instance has been irrevocably disposed of.
* @property {Boolean} disposed
*/
MappedDisposable.prototype.disposed = false;
module.exports = MappedDisposable;