collect-your-stuff 2.1.1 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/README.md +32 -3241
  2. package/browser/collect-your-stuff.js +1585 -1193
  3. package/browser/collect-your-stuff.min.js +1 -1
  4. package/dist/collections/arrayable/ArrayElement.d.ts +33 -38
  5. package/dist/collections/arrayable/ArrayElement.js +64 -66
  6. package/dist/collections/arrayable/Arrayable.d.ts +107 -122
  7. package/dist/collections/arrayable/Arrayable.js +208 -223
  8. package/dist/collections/doubly-linked-list/DoubleLinker.d.ts +45 -50
  9. package/dist/collections/doubly-linked-list/DoubleLinker.js +71 -73
  10. package/dist/collections/doubly-linked-list/DoublyLinkedList.d.ts +108 -125
  11. package/dist/collections/doubly-linked-list/DoublyLinkedList.js +310 -327
  12. package/dist/collections/linked-list/LinkedList.d.ts +110 -126
  13. package/dist/collections/linked-list/LinkedList.js +283 -296
  14. package/dist/collections/linked-list/Linker.d.ts +41 -46
  15. package/dist/collections/linked-list/Linker.js +82 -84
  16. package/dist/collections/linked-tree-list/LinkedTreeList.d.ts +140 -159
  17. package/dist/collections/linked-tree-list/LinkedTreeList.js +274 -294
  18. package/dist/collections/linked-tree-list/TreeLinker.d.ts +65 -71
  19. package/dist/collections/linked-tree-list/TreeLinker.js +91 -94
  20. package/dist/collections/queue/Queue.d.ts +55 -59
  21. package/dist/collections/queue/Queue.js +114 -119
  22. package/dist/collections/queue/Queueable.d.ts +74 -83
  23. package/dist/collections/queue/Queueable.js +142 -146
  24. package/dist/collections/queue/TaskQueue.d.ts +59 -68
  25. package/dist/collections/queue/TaskQueue.js +128 -137
  26. package/dist/collections/scoped-collection/ScopedCollection.d.ts +42 -0
  27. package/dist/collections/scoped-collection/ScopedCollection.js +81 -0
  28. package/dist/collections/scoped-collection/ScopedCollection.min.js +1 -0
  29. package/dist/collections/stack/Stack.d.ts +60 -64
  30. package/dist/collections/stack/Stack.js +122 -127
  31. package/dist/collections/stack/Stackable.d.ts +52 -59
  32. package/dist/collections/stack/Stackable.js +81 -85
  33. package/dist/collections/stack/TaskStack.d.ts +56 -65
  34. package/dist/collections/stack/TaskStack.js +98 -107
  35. package/dist/main.d.ts +4 -5
  36. package/dist/main.js +9 -5
  37. package/dist/main.min.js +1 -1
  38. package/dist/recipes/ArrayIterator.d.ts +20 -20
  39. package/dist/recipes/ArrayIterator.js +39 -39
  40. package/dist/recipes/DoubleLinkerIterator.d.ts +18 -18
  41. package/dist/recipes/DoubleLinkerIterator.js +33 -33
  42. package/dist/recipes/IsArrayable.d.ts +85 -105
  43. package/dist/recipes/IsArrayable.js +5 -5
  44. package/dist/recipes/IsDoubleLinker.d.ts +14 -14
  45. package/dist/recipes/IsDoubleLinker.js +5 -5
  46. package/dist/recipes/IsElement.d.ts +14 -14
  47. package/dist/recipes/IsElement.js +5 -5
  48. package/dist/recipes/IsLinker.d.ts +10 -10
  49. package/dist/recipes/IsLinker.js +5 -5
  50. package/dist/recipes/IsQueue.d.ts +32 -37
  51. package/dist/recipes/IsQueue.js +5 -5
  52. package/dist/recipes/IsScopedCollection.d.ts +27 -0
  53. package/dist/recipes/IsScopedCollection.js +5 -0
  54. package/dist/recipes/IsScopedCollection.min.js +1 -0
  55. package/dist/recipes/IsStack.d.ts +31 -36
  56. package/dist/recipes/IsStack.js +5 -5
  57. package/dist/recipes/IsTree.d.ts +11 -11
  58. package/dist/recipes/IsTree.js +5 -5
  59. package/dist/recipes/IsTreeNode.d.ts +29 -29
  60. package/dist/recipes/IsTreeNode.js +5 -5
  61. package/dist/recipes/LinkerIterator.d.ts +18 -18
  62. package/dist/recipes/LinkerIterator.js +33 -33
  63. package/dist/recipes/Runnable.d.ts +42 -55
  64. package/dist/recipes/Runnable.js +63 -69
  65. package/dist/recipes/TreeLinkerIterator.d.ts +20 -20
  66. package/dist/recipes/TreeLinkerIterator.js +36 -36
  67. package/dist/recipes/recipes.d.ts +12 -15
  68. package/dist/recipes/recipes.js +19 -22
  69. package/dist/services/parseTree.d.ts +8 -9
  70. package/dist/services/parseTree.js +23 -24
  71. package/dist/services/parseTreeNext.d.ts +16 -17
  72. package/dist/services/parseTreeNext.js +41 -42
  73. package/dist/services/services.d.ts +10 -13
  74. package/dist/services/services.js +19 -22
  75. package/package.json +4 -4
@@ -1,327 +1,310 @@
1
- 'use strict'
2
-
3
- Object.defineProperty(exports, '__esModule', {
4
- value: true
5
- })
6
- exports.DoublyLinkedList = void 0
7
- require('core-js/modules/esnext.iterator.constructor.js')
8
- require('core-js/modules/esnext.iterator.for-each.js')
9
- var _DoubleLinker = require('./DoubleLinker')
10
- var _DoubleLinkerIterator = require('../../recipes/DoubleLinkerIterator')
11
- var _LinkedList = require('../linked-list/LinkedList')
12
- /**
13
- * @file doubly linked list.
14
- * @author Joshua Heagle <joshuaheagle@gmail.com>
15
- * @version 1.1.0
16
- * @memberOf module:collect-your-stuff
17
- */
18
-
19
- /**
20
- * DoublyLinkedList represents a collection stored as a LinkedList with prev and next references.
21
- * @extends LinkedList
22
- */
23
- class DoublyLinkedList {
24
- /**
25
- * Create the new DoublyLinkedList instance.
26
- * @param {DoubleLinker} [linkerClass=DoubleLinker] The class used to wrap given data as linkers.
27
- */
28
- constructor (linkerClass = _DoubleLinker.DoubleLinker) {
29
- /** The class used to create this instance, so that it can be recognized as valid without an instanceof check. */
30
- this.classType = DoublyLinkedList
31
- /** A linker of the list (null when the list is empty); the head is found by walking back from it. */
32
- this.innerList = null
33
- /** Whether the inner list has been initialized (it can only be initialized once). */
34
- this.initialized = false
35
- /** The last linker, remembered so that adding to the end does not need to walk the whole list (null when not known yet). */
36
- this.tailCache = null
37
- /** The number of linkers, kept up to date by the list's own methods so that the length does not need to walk the whole list (null when not known yet). */
38
- this.countCache = null
39
- this.linkerClass = linkerClass
40
- }
41
-
42
- /**
43
- * Initialize the inner list, should only run once.
44
- * @param {DoubleLinker} initialList Give the list of double-linkers to start in this doubly linked-list.
45
- * @return {DoublyLinkedList}
46
- */
47
- initialize (initialList) {
48
- // Borrowed from LinkedList, which types its return as a LinkedList although it returns whatever list called it
49
- return _LinkedList.LinkedList.prototype.initialize.call(this, initialList)
50
- }
51
-
52
- /**
53
- * Retrieve the innerList used (the list itself, not a copy).
54
- * @returns {DoubleLinker}
55
- */
56
- get list () {
57
- return this.innerList
58
- }
59
-
60
- /**
61
- * Retrieve the first DoubleLinker in the list.
62
- * @returns {DoubleLinker}
63
- */
64
- get first () {
65
- let head = this.innerList
66
- if (head === null) {
67
- return null
68
- }
69
- // innerList is normally the head already, walking back also finds anything linked on before it outside of this list
70
- while (head.prev !== null) {
71
- head = head.prev
72
- }
73
- this.innerList = head
74
- return head
75
- }
76
-
77
- /**
78
- * Retrieve the last DoubleLinker in the list. The end is remembered, so this does not walk the list.
79
- * @returns {DoubleLinker}
80
- */
81
- get last () {
82
- if (this.innerList === null) {
83
- return null
84
- }
85
- let tail = this.tailCache !== null ? this.tailCache : this.innerList
86
- // The remembered tail is normally the end already, walking on from it also finds anything linked on outside of this list
87
- while (tail.next !== null) {
88
- tail = tail.next
89
- }
90
- this.tailCache = tail
91
- return tail
92
- }
93
-
94
- /**
95
- * Return the length of the list. It is kept up to date by the list's own methods, so this does not walk the list
96
- * (call reset() after linkers were changed directly).
97
- * @returns {number}
98
- */
99
- get length () {
100
- if (this.countCache === null) {
101
- this.reset()
102
- }
103
- return this.countCache
104
- }
105
-
106
- /**
107
- * Insert a new node (or data) after a node.
108
- * @param {DoubleLinker|*} node The existing node as reference (which must be in this list, this is not checked), or null to insert at the start of the list
109
- * @param {DoubleLinker|*} newNode The new node to go after the existing node
110
- * @returns {DoublyLinkedList}
111
- */
112
- insertAfter (node, newNode) {
113
- newNode = this.linkerClass.make(newNode, this.linkerClass)
114
- if (node === null || typeof node === 'undefined') {
115
- // After nothing means at the start of the list
116
- const head = this.first
117
- newNode.prev = null
118
- newNode.next = head
119
- if (head) {
120
- head.prev = newNode
121
- } else {
122
- this.tailCache = newNode
123
- }
124
- this.innerList = newNode
125
- } else {
126
- // Ensure the next reference of this node is assigned to the new node
127
- newNode.next = node.next
128
- // Ensure this node is assigned as the prev reference of the new node
129
- newNode.prev = node
130
- // Then set this node's next reference to the new node
131
- node.next = newNode
132
- if (newNode.next) {
133
- // Update the next reference to ensure circular reference for prev points to the new node
134
- newNode.next.prev = newNode
135
- } else {
136
- this.tailCache = newNode
137
- }
138
- }
139
- if (this.countCache !== null) {
140
- ++this.countCache
141
- }
142
- return this
143
- }
144
-
145
- /**
146
- * Insert a new node (or data) before a node.
147
- * @param {DoubleLinker|*} node The existing node as reference (which must be in this list, this is not checked), or null to insert at the end of the list
148
- * @param {DoubleLinker|*} newNode The new node to go before the existing node
149
- * @returns {DoublyLinkedList}
150
- */
151
- insertBefore (node, newNode) {
152
- newNode = this.linkerClass.make(newNode, this.linkerClass)
153
- if (node === null || typeof node === 'undefined') {
154
- // Before nothing means at the end of the list
155
- const tail = this.last
156
- newNode.next = null
157
- newNode.prev = tail
158
- if (tail === null) {
159
- this.innerList = newNode
160
- } else {
161
- tail.next = newNode
162
- }
163
- this.tailCache = newNode
164
- } else {
165
- // The new node will reference this prev node as prev
166
- newNode.prev = node.prev
167
- // The new node will reference this node as next
168
- newNode.next = node
169
- // This prev will reference the new node
170
- node.prev = newNode
171
- if (newNode.prev) {
172
- // Update the prev reference to ensure circular reference for next points to the new node
173
- newNode.prev.next = newNode
174
- } else {
175
- this.innerList = newNode
176
- }
177
- }
178
- if (this.countCache !== null) {
179
- ++this.countCache
180
- }
181
- return this
182
- }
183
-
184
- /**
185
- * Add a node (or data) after the given (or last) node in the list.
186
- * @param {DoubleLinker|*} node The new node to add to the end of the list
187
- * @param {DoubleLinker} after The existing last node
188
- * @returns {DoubleLinker}
189
- */
190
- append (node, after = this.last) {
191
- return this.insertAfter(after, node)
192
- }
193
-
194
- /**
195
- * Add a node (or data) before the given (or first) node in the list.
196
- * @param {DoubleLinker|*} node The new node to add to the start of the list
197
- * @param {DoubleLinker} before The existing first node
198
- * @returns {DoubleLinker}
199
- */
200
- prepend (node, before = this.first) {
201
- return this.insertBefore(before, node)
202
- }
203
-
204
- /**
205
- * Remove a linker from this linked list.
206
- * @param {DoubleLinker} node The node we wish to remove (and it will be returned after removal)
207
- * @return {DoubleLinker}
208
- */
209
- remove (node) {
210
- if (node === null || typeof node === 'undefined') {
211
- return null
212
- }
213
- if (node.prev) {
214
- // The previous node will reference this next node
215
- node.prev.next = node.next
216
- }
217
- if (node.next) {
218
- // The next node will reference this previous node
219
- node.next.prev = node.prev
220
- }
221
- // The list finds its head by walking from innerList, so it must not keep pointing at the node being removed. For the
222
- // last remaining node there is nothing to walk to, which would otherwise leave the removed node in the list.
223
- if (this.innerList === node) {
224
- this.innerList = node.next || node.prev || null
225
- }
226
- if (this.tailCache === node) {
227
- this.tailCache = node.prev
228
- }
229
- if (this.innerList === null) {
230
- this.tailCache = null
231
- }
232
- if (this.countCache !== null) {
233
- --this.countCache
234
- }
235
- return node
236
- }
237
-
238
- /**
239
- * Refresh all references (the head, the end and the length) by walking the list once, and return the head. The list's
240
- * own methods keep these up to date, so this is only needed after linkers were changed directly.
241
- * @return {DoubleLinker|null}
242
- */
243
- reset () {
244
- // Start at the pointer for the list
245
- let pointer = this.innerList
246
- if (pointer === null) {
247
- this.countCache = 0
248
- this.tailCache = null
249
- return null
250
- }
251
- // Follow references back to the beginning
252
- while (pointer.prev !== null) {
253
- pointer = pointer.prev
254
- }
255
- // We are pointing to the true head, now count along to the end to find the tail and the length
256
- this.innerList = pointer
257
- let count = 0
258
- let tail = pointer
259
- let current = pointer
260
- while (current !== null) {
261
- ++count
262
- tail = current
263
- current = current.next
264
- }
265
- this.countCache = count
266
- this.tailCache = tail
267
- return pointer
268
- }
269
-
270
- /**
271
- * Retrieve a DoubleLinker item from this list by numeric index, otherwise return null.
272
- * @param {number} index The integer number for retrieving a node by position.
273
- * @returns {DoubleLinker|null}
274
- */
275
- item (index) {
276
- if (index >= 0) {
277
- // For a positive index, start from the beginning of the list until the current item counter equals our index
278
- let current = this.first
279
- let currentIndex = -1
280
- while (++currentIndex < index && current !== null) {
281
- current = current.next
282
- }
283
- return currentIndex === index ? current : null
284
- }
285
- // For a negative index, get the delta of index and length, then go backwards until we reach that delta
286
- let current = this.last
287
- let currentIndex = this.length
288
- const calculatedIndex = this.length + index
289
- if (calculatedIndex < 0) {
290
- return null
291
- }
292
- while (--currentIndex > calculatedIndex && current !== null) {
293
- current = current.prev
294
- }
295
- return currentIndex === calculatedIndex ? current : null
296
- }
297
-
298
- /**
299
- * Be able to run forEach on this DoublyLinkedList to iterate over the DoubleLinker Items.
300
- * @param {forEachCallback} callback The function to call for-each double linker
301
- * @param {DoublyLinkedList} thisArg Optional, 'this' reference
302
- * @return {DoublyLinkedList} The list which was iterated.
303
- */
304
- forEach (callback, thisArg = this) {
305
- return _LinkedList.LinkedList.prototype.forEach.call(this, callback, thisArg)
306
- }
307
-
308
- /**
309
- * Be able to iterate over this class.
310
- * @returns {Iterator}
311
- */
312
- [Symbol.iterator] () {
313
- const current = this.first
314
- return new _DoubleLinkerIterator.DoubleLinkerIterator(current)
315
- }
316
- }
317
- /**
318
- * Convert an array into a DoublyLinkedList instance, return the new instance.
319
- * @param {Array} [values=[]] An array of values which will be converted to linkers in this doubly-linked-list
320
- * @param {IsDoubleLinker} [linkerClass=DoubleLinker] The class to use for each linker
321
- * @param {IsArrayable<IsDoubleLinker>} [classType=LinkedList] Provide the type of IsArrayable to use.
322
- * @returns {DoublyLinkedList}
323
- */
324
- exports.DoublyLinkedList = DoublyLinkedList
325
- DoublyLinkedList.fromArray = (values = [], linkerClass = _DoubleLinker.DoubleLinker, classType = DoublyLinkedList) => {
326
- return _LinkedList.LinkedList.fromArray(values, linkerClass, classType)
327
- }
1
+ 'use strict'
2
+
3
+ Object.defineProperty(exports, '__esModule', {
4
+ value: true
5
+ })
6
+ exports.DoublyLinkedList = void 0
7
+ require('core-js/modules/esnext.iterator.constructor.js')
8
+ require('core-js/modules/esnext.iterator.for-each.js')
9
+ const _DoubleLinker = require('./DoubleLinker')
10
+ const _DoubleLinkerIterator = require('../../recipes/DoubleLinkerIterator')
11
+ const _LinkedList = require('../linked-list/LinkedList')
12
+ /**
13
+ * doubly linked list.
14
+ */
15
+
16
+ /**
17
+ * DoublyLinkedList represents a collection stored as a LinkedList with prev and next references.
18
+ * @extends LinkedList
19
+ */
20
+ class DoublyLinkedList {
21
+ /**
22
+ * Create the new DoublyLinkedList instance.
23
+ * @param linkerClass The class used to wrap given data as linkers.
24
+ */
25
+ constructor (linkerClass = _DoubleLinker.DoubleLinker) {
26
+ /** The class used to create this instance, so that it can be recognized as valid without an instanceof check. */
27
+ this.classType = DoublyLinkedList
28
+ /** A linker of the list (null when the list is empty); the head is found by walking back from it. */
29
+ this.innerList = null
30
+ /** Whether the inner list has been initialized (it can only be initialized once). */
31
+ this.initialized = false
32
+ /** The last linker, remembered so that adding to the end does not need to walk the whole list (null when not known yet). */
33
+ this.tailCache = null
34
+ /** The number of linkers, kept up to date by the list's own methods so that the length does not need to walk the whole list (null when not known yet). */
35
+ this.countCache = null
36
+ this.linkerClass = linkerClass
37
+ }
38
+
39
+ /**
40
+ * Initialize the inner list, should only run once.
41
+ * @param initialList Give the list of double-linkers to start in this doubly linked-list.
42
+ */
43
+ initialize (initialList) {
44
+ // Borrowed from LinkedList, which types its return as a LinkedList although it returns whatever list called it
45
+ return _LinkedList.LinkedList.prototype.initialize.call(this, initialList)
46
+ }
47
+
48
+ /**
49
+ * Retrieve the innerList used (the list itself, not a copy).
50
+ */
51
+ get list () {
52
+ return this.innerList
53
+ }
54
+
55
+ /**
56
+ * Retrieve the first DoubleLinker in the list.
57
+ */
58
+ get first () {
59
+ let head = this.innerList
60
+ if (head === null) {
61
+ return null
62
+ }
63
+ // innerList is normally the head already, walking back also finds anything linked on before it outside of this list
64
+ while (head.prev !== null) {
65
+ head = head.prev
66
+ }
67
+ this.innerList = head
68
+ return head
69
+ }
70
+
71
+ /**
72
+ * Retrieve the last DoubleLinker in the list. The end is remembered, so this does not walk the list.
73
+ */
74
+ get last () {
75
+ if (this.innerList === null) {
76
+ return null
77
+ }
78
+ let tail = this.tailCache !== null ? this.tailCache : this.innerList
79
+ // The remembered tail is normally the end already, walking on from it also finds anything linked on outside of this list
80
+ while (tail.next !== null) {
81
+ tail = tail.next
82
+ }
83
+ this.tailCache = tail
84
+ return tail
85
+ }
86
+
87
+ /**
88
+ * Return the length of the list. It is kept up to date by the list's own methods, so this does not walk the list
89
+ * (call reset() after linkers were changed directly).
90
+ */
91
+ get length () {
92
+ if (this.countCache === null) {
93
+ this.reset()
94
+ }
95
+ return this.countCache
96
+ }
97
+
98
+ /**
99
+ * Insert a new node (or data) after a node.
100
+ * @param node The existing node as reference (which must be in this list, this is not checked), or null to insert at the start of the list
101
+ * @param newNode The new node to go after the existing node
102
+ */
103
+ insertAfter (node, newNode) {
104
+ newNode = this.linkerClass.make(newNode, this.linkerClass)
105
+ if (node === null || typeof node === 'undefined') {
106
+ // After nothing means at the start of the list
107
+ const head = this.first
108
+ newNode.prev = null
109
+ newNode.next = head
110
+ if (head) {
111
+ head.prev = newNode
112
+ } else {
113
+ this.tailCache = newNode
114
+ }
115
+ this.innerList = newNode
116
+ } else {
117
+ // Ensure the next reference of this node is assigned to the new node
118
+ newNode.next = node.next
119
+ // Ensure this node is assigned as the prev reference of the new node
120
+ newNode.prev = node
121
+ // Then set this node's next reference to the new node
122
+ node.next = newNode
123
+ if (newNode.next) {
124
+ // Update the next reference to ensure circular reference for prev points to the new node
125
+ newNode.next.prev = newNode
126
+ } else {
127
+ this.tailCache = newNode
128
+ }
129
+ }
130
+ if (this.countCache !== null) {
131
+ ++this.countCache
132
+ }
133
+ return this
134
+ }
135
+
136
+ /**
137
+ * Insert a new node (or data) before a node.
138
+ * @param node The existing node as reference (which must be in this list, this is not checked), or null to insert at the end of the list
139
+ * @param newNode The new node to go before the existing node
140
+ */
141
+ insertBefore (node, newNode) {
142
+ newNode = this.linkerClass.make(newNode, this.linkerClass)
143
+ if (node === null || typeof node === 'undefined') {
144
+ // Before nothing means at the end of the list
145
+ const tail = this.last
146
+ newNode.next = null
147
+ newNode.prev = tail
148
+ if (tail === null) {
149
+ this.innerList = newNode
150
+ } else {
151
+ tail.next = newNode
152
+ }
153
+ this.tailCache = newNode
154
+ } else {
155
+ // The new node will reference this prev node as prev
156
+ newNode.prev = node.prev
157
+ // The new node will reference this node as next
158
+ newNode.next = node
159
+ // This prev will reference the new node
160
+ node.prev = newNode
161
+ if (newNode.prev) {
162
+ // Update the prev reference to ensure circular reference for next points to the new node
163
+ newNode.prev.next = newNode
164
+ } else {
165
+ this.innerList = newNode
166
+ }
167
+ }
168
+ if (this.countCache !== null) {
169
+ ++this.countCache
170
+ }
171
+ return this
172
+ }
173
+
174
+ /**
175
+ * Add a node (or data) after the given (or last) node in the list.
176
+ * @param node The new node to add to the end of the list
177
+ * @param after The existing last node
178
+ */
179
+ append (node, after = this.last) {
180
+ return this.insertAfter(after, node)
181
+ }
182
+
183
+ /**
184
+ * Add a node (or data) before the given (or first) node in the list.
185
+ * @param node The new node to add to the start of the list
186
+ * @param before The existing first node
187
+ */
188
+ prepend (node, before = this.first) {
189
+ return this.insertBefore(before, node)
190
+ }
191
+
192
+ /**
193
+ * Remove a linker from this linked list.
194
+ * @param node The node we wish to remove (and it will be returned after removal)
195
+ */
196
+ remove (node) {
197
+ if (node === null || typeof node === 'undefined') {
198
+ return null
199
+ }
200
+ if (node.prev) {
201
+ // The previous node will reference this next node
202
+ node.prev.next = node.next
203
+ }
204
+ if (node.next) {
205
+ // The next node will reference this previous node
206
+ node.next.prev = node.prev
207
+ }
208
+ // The list finds its head by walking from innerList, so it must not keep pointing at the node being removed. For the
209
+ // last remaining node there is nothing to walk to, which would otherwise leave the removed node in the list.
210
+ if (this.innerList === node) {
211
+ this.innerList = node.next || node.prev || null
212
+ }
213
+ if (this.tailCache === node) {
214
+ this.tailCache = node.prev
215
+ }
216
+ if (this.innerList === null) {
217
+ this.tailCache = null
218
+ }
219
+ if (this.countCache !== null) {
220
+ --this.countCache
221
+ }
222
+ return node
223
+ }
224
+
225
+ /**
226
+ * Refresh all references (the head, the end and the length) by walking the list once, and return the head. The list's
227
+ * own methods keep these up to date, so this is only needed after linkers were changed directly.
228
+ */
229
+ reset () {
230
+ // Start at the pointer for the list
231
+ let pointer = this.innerList
232
+ if (pointer === null) {
233
+ this.countCache = 0
234
+ this.tailCache = null
235
+ return null
236
+ }
237
+ // Follow references back to the beginning
238
+ while (pointer.prev !== null) {
239
+ pointer = pointer.prev
240
+ }
241
+ // We are pointing to the true head, now count along to the end to find the tail and the length
242
+ this.innerList = pointer
243
+ let count = 0
244
+ let tail = pointer
245
+ let current = pointer
246
+ while (current !== null) {
247
+ ++count
248
+ tail = current
249
+ current = current.next
250
+ }
251
+ this.countCache = count
252
+ this.tailCache = tail
253
+ return pointer
254
+ }
255
+
256
+ /**
257
+ * Retrieve a DoubleLinker item from this list by numeric index, otherwise return null.
258
+ * @param index The integer number for retrieving a node by position.
259
+ */
260
+ item (index) {
261
+ if (index >= 0) {
262
+ // For a positive index, start from the beginning of the list until the current item counter equals our index
263
+ let current = this.first
264
+ let currentIndex = -1
265
+ while (++currentIndex < index && current !== null) {
266
+ current = current.next
267
+ }
268
+ return currentIndex === index ? current : null
269
+ }
270
+ // For a negative index, get the delta of index and length, then go backwards until we reach that delta
271
+ let current = this.last
272
+ let currentIndex = this.length
273
+ const calculatedIndex = this.length + index
274
+ if (calculatedIndex < 0) {
275
+ return null
276
+ }
277
+ while (--currentIndex > calculatedIndex && current !== null) {
278
+ current = current.prev
279
+ }
280
+ return currentIndex === calculatedIndex ? current : null
281
+ }
282
+
283
+ /**
284
+ * Be able to run forEach on this DoublyLinkedList to iterate over the DoubleLinker Items.
285
+ * @param callback The function to call for-each double linker
286
+ * @param thisArg Optional, 'this' reference
287
+ * @returns The list which was iterated.
288
+ */
289
+ forEach (callback, thisArg = this) {
290
+ return _LinkedList.LinkedList.prototype.forEach.call(this, callback, thisArg)
291
+ }
292
+
293
+ /**
294
+ * Be able to iterate over this class.
295
+ */
296
+ [Symbol.iterator] () {
297
+ const current = this.first
298
+ return new _DoubleLinkerIterator.DoubleLinkerIterator(current)
299
+ }
300
+ }
301
+ /**
302
+ * Convert an array into a DoublyLinkedList instance, return the new instance.
303
+ * @param values An array of values which will be converted to linkers in this doubly-linked-list
304
+ * @param linkerClass The class to use for each linker
305
+ * @param classType Provide the type of IsArrayable to use.
306
+ */
307
+ exports.DoublyLinkedList = DoublyLinkedList
308
+ DoublyLinkedList.fromArray = (values = [], linkerClass = _DoubleLinker.DoubleLinker, classType = DoublyLinkedList) => {
309
+ return _LinkedList.LinkedList.fromArray(values, linkerClass, classType)
310
+ }