You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					427 lines
				
				8.2 KiB
			
		
		
			
		
	
	
					427 lines
				
				8.2 KiB
			| 
											3 years ago
										 | 'use strict' | ||
|  | module.exports = Yallist | ||
|  | 
 | ||
|  | Yallist.Node = Node | ||
|  | Yallist.create = Yallist | ||
|  | 
 | ||
|  | function Yallist (list) { | ||
|  |   var self = this | ||
|  |   if (!(self instanceof Yallist)) { | ||
|  |     self = new Yallist() | ||
|  |   } | ||
|  | 
 | ||
|  |   self.tail = null | ||
|  |   self.head = null | ||
|  |   self.length = 0 | ||
|  | 
 | ||
|  |   if (list && typeof list.forEach === 'function') { | ||
|  |     list.forEach(function (item) { | ||
|  |       self.push(item) | ||
|  |     }) | ||
|  |   } else if (arguments.length > 0) { | ||
|  |     for (var i = 0, l = arguments.length; i < l; i++) { | ||
|  |       self.push(arguments[i]) | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   return self | ||
|  | } | ||
|  | 
 | ||
|  | Yallist.prototype.removeNode = function (node) { | ||
|  |   if (node.list !== this) { | ||
|  |     throw new Error('removing node which does not belong to this list') | ||
|  |   } | ||
|  | 
 | ||
|  |   var next = node.next | ||
|  |   var prev = node.prev | ||
|  | 
 | ||
|  |   if (next) { | ||
|  |     next.prev = prev | ||
|  |   } | ||
|  | 
 | ||
|  |   if (prev) { | ||
|  |     prev.next = next | ||
|  |   } | ||
|  | 
 | ||
|  |   if (node === this.head) { | ||
|  |     this.head = next | ||
|  |   } | ||
|  |   if (node === this.tail) { | ||
|  |     this.tail = prev | ||
|  |   } | ||
|  | 
 | ||
|  |   node.list.length-- | ||
|  |   node.next = null | ||
|  |   node.prev = null | ||
|  |   node.list = null | ||
|  | 
 | ||
|  |   return next | ||
|  | } | ||
|  | 
 | ||
|  | Yallist.prototype.unshiftNode = function (node) { | ||
|  |   if (node === this.head) { | ||
|  |     return | ||
|  |   } | ||
|  | 
 | ||
|  |   if (node.list) { | ||
|  |     node.list.removeNode(node) | ||
|  |   } | ||
|  | 
 | ||
|  |   var head = this.head | ||
|  |   node.list = this | ||
|  |   node.next = head | ||
|  |   if (head) { | ||
|  |     head.prev = node | ||
|  |   } | ||
|  | 
 | ||
|  |   this.head = node | ||
|  |   if (!this.tail) { | ||
|  |     this.tail = node | ||
|  |   } | ||
|  |   this.length++ | ||
|  | } | ||
|  | 
 | ||
|  | Yallist.prototype.pushNode = function (node) { | ||
|  |   if (node === this.tail) { | ||
|  |     return | ||
|  |   } | ||
|  | 
 | ||
|  |   if (node.list) { | ||
|  |     node.list.removeNode(node) | ||
|  |   } | ||
|  | 
 | ||
|  |   var tail = this.tail | ||
|  |   node.list = this | ||
|  |   node.prev = tail | ||
|  |   if (tail) { | ||
|  |     tail.next = node | ||
|  |   } | ||
|  | 
 | ||
|  |   this.tail = node | ||
|  |   if (!this.head) { | ||
|  |     this.head = node | ||
|  |   } | ||
|  |   this.length++ | ||
|  | } | ||
|  | 
 | ||
|  | Yallist.prototype.push = function () { | ||
|  |   for (var i = 0, l = arguments.length; i < l; i++) { | ||
|  |     push(this, arguments[i]) | ||
|  |   } | ||
|  |   return this.length | ||
|  | } | ||
|  | 
 | ||
|  | Yallist.prototype.unshift = function () { | ||
|  |   for (var i = 0, l = arguments.length; i < l; i++) { | ||
|  |     unshift(this, arguments[i]) | ||
|  |   } | ||
|  |   return this.length | ||
|  | } | ||
|  | 
 | ||
|  | Yallist.prototype.pop = function () { | ||
|  |   if (!this.tail) { | ||
|  |     return undefined | ||
|  |   } | ||
|  | 
 | ||
|  |   var res = this.tail.value | ||
|  |   this.tail = this.tail.prev | ||
|  |   if (this.tail) { | ||
|  |     this.tail.next = null | ||
|  |   } else { | ||
|  |     this.head = null | ||
|  |   } | ||
|  |   this.length-- | ||
|  |   return res | ||
|  | } | ||
|  | 
 | ||
|  | Yallist.prototype.shift = function () { | ||
|  |   if (!this.head) { | ||
|  |     return undefined | ||
|  |   } | ||
|  | 
 | ||
|  |   var res = this.head.value | ||
|  |   this.head = this.head.next | ||
|  |   if (this.head) { | ||
|  |     this.head.prev = null | ||
|  |   } else { | ||
|  |     this.tail = null | ||
|  |   } | ||
|  |   this.length-- | ||
|  |   return res | ||
|  | } | ||
|  | 
 | ||
|  | Yallist.prototype.forEach = function (fn, thisp) { | ||
|  |   thisp = thisp || this | ||
|  |   for (var walker = this.head, i = 0; walker !== null; i++) { | ||
|  |     fn.call(thisp, walker.value, i, this) | ||
|  |     walker = walker.next | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | Yallist.prototype.forEachReverse = function (fn, thisp) { | ||
|  |   thisp = thisp || this | ||
|  |   for (var walker = this.tail, i = this.length - 1; walker !== null; i--) { | ||
|  |     fn.call(thisp, walker.value, i, this) | ||
|  |     walker = walker.prev | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | Yallist.prototype.get = function (n) { | ||
|  |   for (var i = 0, walker = this.head; walker !== null && i < n; i++) { | ||
|  |     // abort out of the list early if we hit a cycle
 | ||
|  |     walker = walker.next | ||
|  |   } | ||
|  |   if (i === n && walker !== null) { | ||
|  |     return walker.value | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | Yallist.prototype.getReverse = function (n) { | ||
|  |   for (var i = 0, walker = this.tail; walker !== null && i < n; i++) { | ||
|  |     // abort out of the list early if we hit a cycle
 | ||
|  |     walker = walker.prev | ||
|  |   } | ||
|  |   if (i === n && walker !== null) { | ||
|  |     return walker.value | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | Yallist.prototype.map = function (fn, thisp) { | ||
|  |   thisp = thisp || this | ||
|  |   var res = new Yallist() | ||
|  |   for (var walker = this.head; walker !== null;) { | ||
|  |     res.push(fn.call(thisp, walker.value, this)) | ||
|  |     walker = walker.next | ||
|  |   } | ||
|  |   return res | ||
|  | } | ||
|  | 
 | ||
|  | Yallist.prototype.mapReverse = function (fn, thisp) { | ||
|  |   thisp = thisp || this | ||
|  |   var res = new Yallist() | ||
|  |   for (var walker = this.tail; walker !== null;) { | ||
|  |     res.push(fn.call(thisp, walker.value, this)) | ||
|  |     walker = walker.prev | ||
|  |   } | ||
|  |   return res | ||
|  | } | ||
|  | 
 | ||
|  | Yallist.prototype.reduce = function (fn, initial) { | ||
|  |   var acc | ||
|  |   var walker = this.head | ||
|  |   if (arguments.length > 1) { | ||
|  |     acc = initial | ||
|  |   } else if (this.head) { | ||
|  |     walker = this.head.next | ||
|  |     acc = this.head.value | ||
|  |   } else { | ||
|  |     throw new TypeError('Reduce of empty list with no initial value') | ||
|  |   } | ||
|  | 
 | ||
|  |   for (var i = 0; walker !== null; i++) { | ||
|  |     acc = fn(acc, walker.value, i) | ||
|  |     walker = walker.next | ||
|  |   } | ||
|  | 
 | ||
|  |   return acc | ||
|  | } | ||
|  | 
 | ||
|  | Yallist.prototype.reduceReverse = function (fn, initial) { | ||
|  |   var acc | ||
|  |   var walker = this.tail | ||
|  |   if (arguments.length > 1) { | ||
|  |     acc = initial | ||
|  |   } else if (this.tail) { | ||
|  |     walker = this.tail.prev | ||
|  |     acc = this.tail.value | ||
|  |   } else { | ||
|  |     throw new TypeError('Reduce of empty list with no initial value') | ||
|  |   } | ||
|  | 
 | ||
|  |   for (var i = this.length - 1; walker !== null; i--) { | ||
|  |     acc = fn(acc, walker.value, i) | ||
|  |     walker = walker.prev | ||
|  |   } | ||
|  | 
 | ||
|  |   return acc | ||
|  | } | ||
|  | 
 | ||
|  | Yallist.prototype.toArray = function () { | ||
|  |   var arr = new Array(this.length) | ||
|  |   for (var i = 0, walker = this.head; walker !== null; i++) { | ||
|  |     arr[i] = walker.value | ||
|  |     walker = walker.next | ||
|  |   } | ||
|  |   return arr | ||
|  | } | ||
|  | 
 | ||
|  | Yallist.prototype.toArrayReverse = function () { | ||
|  |   var arr = new Array(this.length) | ||
|  |   for (var i = 0, walker = this.tail; walker !== null; i++) { | ||
|  |     arr[i] = walker.value | ||
|  |     walker = walker.prev | ||
|  |   } | ||
|  |   return arr | ||
|  | } | ||
|  | 
 | ||
|  | Yallist.prototype.slice = function (from, to) { | ||
|  |   to = to || this.length | ||
|  |   if (to < 0) { | ||
|  |     to += this.length | ||
|  |   } | ||
|  |   from = from || 0 | ||
|  |   if (from < 0) { | ||
|  |     from += this.length | ||
|  |   } | ||
|  |   var ret = new Yallist() | ||
|  |   if (to < from || to < 0) { | ||
|  |     return ret | ||
|  |   } | ||
|  |   if (from < 0) { | ||
|  |     from = 0 | ||
|  |   } | ||
|  |   if (to > this.length) { | ||
|  |     to = this.length | ||
|  |   } | ||
|  |   for (var i = 0, walker = this.head; walker !== null && i < from; i++) { | ||
|  |     walker = walker.next | ||
|  |   } | ||
|  |   for (; walker !== null && i < to; i++, walker = walker.next) { | ||
|  |     ret.push(walker.value) | ||
|  |   } | ||
|  |   return ret | ||
|  | } | ||
|  | 
 | ||
|  | Yallist.prototype.sliceReverse = function (from, to) { | ||
|  |   to = to || this.length | ||
|  |   if (to < 0) { | ||
|  |     to += this.length | ||
|  |   } | ||
|  |   from = from || 0 | ||
|  |   if (from < 0) { | ||
|  |     from += this.length | ||
|  |   } | ||
|  |   var ret = new Yallist() | ||
|  |   if (to < from || to < 0) { | ||
|  |     return ret | ||
|  |   } | ||
|  |   if (from < 0) { | ||
|  |     from = 0 | ||
|  |   } | ||
|  |   if (to > this.length) { | ||
|  |     to = this.length | ||
|  |   } | ||
|  |   for (var i = this.length, walker = this.tail; walker !== null && i > to; i--) { | ||
|  |     walker = walker.prev | ||
|  |   } | ||
|  |   for (; walker !== null && i > from; i--, walker = walker.prev) { | ||
|  |     ret.push(walker.value) | ||
|  |   } | ||
|  |   return ret | ||
|  | } | ||
|  | 
 | ||
|  | Yallist.prototype.splice = function (start, deleteCount /*, ...nodes */) { | ||
|  |   if (start > this.length) { | ||
|  |     start = this.length - 1 | ||
|  |   } | ||
|  |   if (start < 0) { | ||
|  |     start = this.length + start; | ||
|  |   } | ||
|  | 
 | ||
|  |   for (var i = 0, walker = this.head; walker !== null && i < start; i++) { | ||
|  |     walker = walker.next | ||
|  |   } | ||
|  | 
 | ||
|  |   var ret = [] | ||
|  |   for (var i = 0; walker && i < deleteCount; i++) { | ||
|  |     ret.push(walker.value) | ||
|  |     walker = this.removeNode(walker) | ||
|  |   } | ||
|  |   if (walker === null) { | ||
|  |     walker = this.tail | ||
|  |   } | ||
|  | 
 | ||
|  |   if (walker !== this.head && walker !== this.tail) { | ||
|  |     walker = walker.prev | ||
|  |   } | ||
|  | 
 | ||
|  |   for (var i = 2; i < arguments.length; i++) { | ||
|  |     walker = insert(this, walker, arguments[i]) | ||
|  |   } | ||
|  |   return ret; | ||
|  | } | ||
|  | 
 | ||
|  | Yallist.prototype.reverse = function () { | ||
|  |   var head = this.head | ||
|  |   var tail = this.tail | ||
|  |   for (var walker = head; walker !== null; walker = walker.prev) { | ||
|  |     var p = walker.prev | ||
|  |     walker.prev = walker.next | ||
|  |     walker.next = p | ||
|  |   } | ||
|  |   this.head = tail | ||
|  |   this.tail = head | ||
|  |   return this | ||
|  | } | ||
|  | 
 | ||
|  | function insert (self, node, value) { | ||
|  |   var inserted = node === self.head ? | ||
|  |     new Node(value, null, node, self) : | ||
|  |     new Node(value, node, node.next, self) | ||
|  | 
 | ||
|  |   if (inserted.next === null) { | ||
|  |     self.tail = inserted | ||
|  |   } | ||
|  |   if (inserted.prev === null) { | ||
|  |     self.head = inserted | ||
|  |   } | ||
|  | 
 | ||
|  |   self.length++ | ||
|  | 
 | ||
|  |   return inserted | ||
|  | } | ||
|  | 
 | ||
|  | function push (self, item) { | ||
|  |   self.tail = new Node(item, self.tail, null, self) | ||
|  |   if (!self.head) { | ||
|  |     self.head = self.tail | ||
|  |   } | ||
|  |   self.length++ | ||
|  | } | ||
|  | 
 | ||
|  | function unshift (self, item) { | ||
|  |   self.head = new Node(item, null, self.head, self) | ||
|  |   if (!self.tail) { | ||
|  |     self.tail = self.head | ||
|  |   } | ||
|  |   self.length++ | ||
|  | } | ||
|  | 
 | ||
|  | function Node (value, prev, next, list) { | ||
|  |   if (!(this instanceof Node)) { | ||
|  |     return new Node(value, prev, next, list) | ||
|  |   } | ||
|  | 
 | ||
|  |   this.list = list | ||
|  |   this.value = value | ||
|  | 
 | ||
|  |   if (prev) { | ||
|  |     prev.next = this | ||
|  |     this.prev = prev | ||
|  |   } else { | ||
|  |     this.prev = null | ||
|  |   } | ||
|  | 
 | ||
|  |   if (next) { | ||
|  |     next.prev = this | ||
|  |     this.next = next | ||
|  |   } else { | ||
|  |     this.next = null | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | try { | ||
|  |   // add if support for Symbol.iterator is present
 | ||
|  |   require('./iterator.js')(Yallist) | ||
|  | } catch (er) {} |