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