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
						
					
					
				| '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) {}
 |