codekingpro/portable-devtools
114k
1export class Yallist {
2 tail;
3 head;
4 length = 0;
5 static create(list = []) {
6 return new Yallist(list);
7 }
8 constructor(list = []) {
9 for (const item of list) {
10 this.push(item);
11 }
12 }
13 *[Symbol.iterator]() {
14 for (let walker = this.head; walker; walker = walker.next) {
15 yield walker.value;
16 }
17 }
18 removeNode(node) {
19 if (node.list !== this) {
20 throw new Error('removing node which does not belong to this list');
21 }
22 const next = node.next;
23 const prev = node.prev;
24 if (next) {
25 next.prev = prev;
26 }
27 if (prev) {
28 prev.next = next;
29 }
30 if (node === this.head) {
31 this.head = next;
32 }
33 if (node === this.tail) {
34 this.tail = prev;
35 }
36 this.length--;
37 node.next = undefined;
38 node.prev = undefined;
39 node.list = undefined;
40 return next;
41 }
42 unshiftNode(node) {
43 if (node === this.head) {
44 return;
45 }
46 if (node.list) {
47 node.list.removeNode(node);
48 }
49 const head = this.head;
50 node.list = this;
51 node.next = head;
52 if (head) {
53 head.prev = node;
54 }
55 this.head = node;
56 if (!this.tail) {
57 this.tail = node;
58 }
59 this.length++;
60 }
61 pushNode(node) {
62 if (node === this.tail) {
63 return;
64 }
65 if (node.list) {
66 node.list.removeNode(node);
67 }
68 const tail = this.tail;
69 node.list = this;
70 node.prev = tail;
71 if (tail) {
72 tail.next = node;
73 }
74 this.tail = node;
75 if (!this.head) {
76 this.head = node;
77 }
78 this.length++;
79 }
80 push(...args) {
81 for (let i = 0, l = args.length; i < l; i++) {
82 push(this, args[i]);
83 }
84 return this.length;
85 }
86 unshift(...args) {
87 for (var i = 0, l = args.length; i < l; i++) {
88 unshift(this, args[i]);
89 }
90 return this.length;
91 }
92 pop() {
93 if (!this.tail) {
94 return undefined;
95 }
96 const res = this.tail.value;
97 const t = this.tail;
98 this.tail = this.tail.prev;
99 if (this.tail) {
100 this.tail.next = undefined;
101 }
102 else {
103 this.head = undefined;
104 }
105 t.list = undefined;
106 this.length--;
107 return res;
108 }
109 shift() {
110 if (!this.head) {
111 return undefined;
112 }
113 const res = this.head.value;
114 const h = this.head;
115 this.head = this.head.next;
116 if (this.head) {
117 this.head.prev = undefined;
118 }
119 else {
120 this.tail = undefined;
121 }
122 h.list = undefined;
123 this.length--;
124 return res;
125 }
126 forEach(fn, thisp) {
127 thisp = thisp || this;
128 for (let walker = this.head, i = 0; !!walker; i++) {
129 fn.call(thisp, walker.value, i, this);
130 walker = walker.next;
131 }
132 }
133 forEachReverse(fn, thisp) {
134 thisp = thisp || this;
135 for (let walker = this.tail, i = this.length - 1; !!walker; i--) {
136 fn.call(thisp, walker.value, i, this);
137 walker = walker.prev;
138 }
139 }
140 get(n) {
141 let i = 0;
142 let walker = this.head;
143 for (; !!walker && i < n; i++) {
144 walker = walker.next;
145 }
146 if (i === n && !!walker) {
147 return walker.value;
148 }
149 }
150 getReverse(n) {
151 let i = 0;
152 let walker = this.tail;
153 for (; !!walker && i < n; i++) {
154 // abort out of the list early if we hit a cycle
155 walker = walker.prev;
156 }
157 if (i === n && !!walker) {
158 return walker.value;
159 }
160 }
161 map(fn, thisp) {
162 thisp = thisp || this;
163 const res = new Yallist();
164 for (let walker = this.head; !!walker;) {
165 res.push(fn.call(thisp, walker.value, this));
166 walker = walker.next;
167 }
168 return res;
169 }
170 mapReverse(fn, thisp) {
171 thisp = thisp || this;
172 var res = new Yallist();
173 for (let walker = this.tail; !!walker;) {
174 res.push(fn.call(thisp, walker.value, this));
175 walker = walker.prev;
176 }
177 return res;
178 }
179 reduce(fn, initial) {
180 let acc;
181 let walker = this.head;
182 if (arguments.length > 1) {
183 acc = initial;
184 }
185 else if (this.head) {
186 walker = this.head.next;
187 acc = this.head.value;
188 }
189 else {
190 throw new TypeError('Reduce of empty list with no initial value');
191 }
192 for (var i = 0; !!walker; i++) {
193 acc = fn(acc, walker.value, i);
194 walker = walker.next;
195 }
196 return acc;
197 }
198 reduceReverse(fn, initial) {
199 let acc;
200 let walker = this.tail;
201 if (arguments.length > 1) {
202 acc = initial;
203 }
204 else if (this.tail) {
205 walker = this.tail.prev;
206 acc = this.tail.value;
207 }
208 else {
209 throw new TypeError('Reduce of empty list with no initial value');
210 }
211 for (let i = this.length - 1; !!walker; i--) {
212 acc = fn(acc, walker.value, i);
213 walker = walker.prev;
214 }
215 return acc;
216 }
217 toArray() {
218 const arr = new Array(this.length);
219 for (let i = 0, walker = this.head; !!walker; i++) {
220 arr[i] = walker.value;
221 walker = walker.next;
222 }
223 return arr;
224 }
225 toArrayReverse() {
226 const arr = new Array(this.length);
227 for (let i = 0, walker = this.tail; !!walker; i++) {
228 arr[i] = walker.value;
229 walker = walker.prev;
230 }
231 return arr;
232 }
233 slice(from = 0, to = this.length) {
234 if (to < 0) {
235 to += this.length;
236 }
237 if (from < 0) {
238 from += this.length;
239 }
240 const ret = new Yallist();
241 if (to < from || to < 0) {
242 return ret;
243 }
244 if (from < 0) {
245 from = 0;
246 }
247 if (to > this.length) {
248 to = this.length;
249 }
250 let walker = this.head;
251 let i = 0;
252 for (i = 0; !!walker && i < from; i++) {
253 walker = walker.next;
254 }
255 for (; !!walker && i < to; i++, walker = walker.next) {
256 ret.push(walker.value);
257 }
258 return ret;
259 }
260 sliceReverse(from = 0, to = this.length) {
261 if (to < 0) {
262 to += this.length;
263 }
264 if (from < 0) {
265 from += this.length;
266 }
267 const ret = new Yallist();
268 if (to < from || to < 0) {
269 return ret;
270 }
271 if (from < 0) {
272 from = 0;
273 }
274 if (to > this.length) {
275 to = this.length;
276 }
277 let i = this.length;
278 let walker = this.tail;
279 for (; !!walker && i > to; i--) {
280 walker = walker.prev;
281 }
282 for (; !!walker && i > from; i--, walker = walker.prev) {
283 ret.push(walker.value);
284 }
285 return ret;
286 }
287 splice(start, deleteCount = 0, ...nodes) {
288 if (start > this.length) {
289 start = this.length - 1;
290 }
291 if (start < 0) {
292 start = this.length + start;
293 }
294 let walker = this.head;
295 for (let i = 0; !!walker && i < start; i++) {
296 walker = walker.next;
297 }
298 const ret = [];
299 for (let i = 0; !!walker && i < deleteCount; i++) {
300 ret.push(walker.value);
301 walker = this.removeNode(walker);
302 }
303 if (!walker) {
304 walker = this.tail;
305 }
306 else if (walker !== this.tail) {
307 walker = walker.prev;
308 }
309 for (const v of nodes) {
310 walker = insertAfter(this, walker, v);
311 }
312 return ret;
313 }
314 reverse() {
315 const head = this.head;
316 const tail = this.tail;
317 for (let walker = head; !!walker; walker = walker.prev) {
318 const p = walker.prev;
319 walker.prev = walker.next;
320 walker.next = p;
321 }
322 this.head = tail;
323 this.tail = head;
324 return this;
325 }
326}
327// insertAfter undefined means "make the node the new head of list"
328function insertAfter(self, node, value) {
329 const prev = node;
330 const next = node ? node.next : self.head;
331 const inserted = new Node(value, prev, next, self);
332 if (inserted.next === undefined) {
333 self.tail = inserted;
334 }
335 if (inserted.prev === undefined) {
336 self.head = inserted;
337 }
338 self.length++;
339 return inserted;
340}
341function push(self, item) {
342 self.tail = new Node(item, self.tail, undefined, self);
343 if (!self.head) {
344 self.head = self.tail;
345 }
346 self.length++;
347}
348function unshift(self, item) {
349 self.head = new Node(item, undefined, self.head, self);
350 if (!self.tail) {
351 self.tail = self.head;
352 }
353 self.length++;
354}
355export class Node {
356 list;
357 next;
358 prev;
359 value;
360 constructor(value, prev, next, list) {
361 this.list = list;
362 this.value = value;
363 if (prev) {
364 prev.next = this;
365 this.prev = prev;
366 }
367 else {
368 this.prev = undefined;
369 }
370 if (next) {
371 next.prev = this;
372 this.next = next;
373 }
374 else {
375 this.next = undefined;
376 }
377 }
378}
379//# sourceMappingURL=index.js.map