list-toolkit 2.2.5 → 2.3.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 (125) hide show
  1. package/README.md +40 -36
  2. package/llms-full.txt +743 -0
  3. package/llms.txt +100 -0
  4. package/package.json +40 -32
  5. package/src/cache/cache-fifo.d.ts +6 -0
  6. package/src/cache/cache-fifo.js +7 -4
  7. package/src/cache/cache-lfu.d.ts +18 -0
  8. package/src/cache/cache-lfu.js +18 -6
  9. package/src/cache/cache-lru.d.ts +74 -0
  10. package/src/cache/cache-lru.js +60 -5
  11. package/src/cache/cache-random.d.ts +20 -0
  12. package/src/cache/cache-random.js +17 -6
  13. package/src/cache/decorator.d.ts +46 -0
  14. package/src/cache/decorator.js +26 -2
  15. package/src/cache.d.ts +13 -0
  16. package/src/cache.js +7 -2
  17. package/src/ext-list.d.ts +3 -0
  18. package/src/ext-list.js +0 -2
  19. package/src/ext-slist.d.ts +3 -0
  20. package/src/ext-slist.js +0 -2
  21. package/src/ext-value-list.d.ts +3 -0
  22. package/src/ext-value-list.js +0 -2
  23. package/src/ext-value-slist.d.ts +3 -0
  24. package/src/ext-value-slist.js +0 -2
  25. package/src/heap/basics.d.ts +89 -0
  26. package/src/heap/basics.js +42 -5
  27. package/src/heap/leftist-heap.d.ts +107 -0
  28. package/src/heap/leftist-heap.js +54 -2
  29. package/src/heap/min-heap.d.ts +270 -0
  30. package/src/heap/min-heap.js +186 -2
  31. package/src/heap/skew-heap.d.ts +105 -0
  32. package/src/heap/skew-heap.js +54 -2
  33. package/src/heap.d.ts +3 -0
  34. package/src/heap.js +0 -2
  35. package/src/list/basics.d.ts +43 -0
  36. package/src/list/basics.js +26 -8
  37. package/src/list/core.d.ts +271 -0
  38. package/src/list/core.js +162 -7
  39. package/src/list/ext-value.d.ts +253 -0
  40. package/src/list/ext-value.js +40 -6
  41. package/src/list/ext.d.ts +242 -0
  42. package/src/list/ext.js +148 -10
  43. package/src/list/nodes.d.ts +336 -0
  44. package/src/list/nodes.js +141 -3
  45. package/src/list/ptr.d.ts +72 -0
  46. package/src/list/ptr.js +44 -2
  47. package/src/list/value.d.ts +292 -0
  48. package/src/list/value.js +47 -6
  49. package/src/list-helpers.d.ts +44 -0
  50. package/src/list-helpers.js +36 -3
  51. package/src/list-utils.d.ts +141 -0
  52. package/src/list-utils.js +89 -3
  53. package/src/list.d.ts +3 -0
  54. package/src/list.js +0 -2
  55. package/src/meta-utils.d.ts +212 -0
  56. package/src/meta-utils.js +152 -1
  57. package/src/nt-utils.d.ts +91 -0
  58. package/src/nt-utils.js +65 -4
  59. package/src/queue.d.ts +74 -0
  60. package/src/queue.js +28 -2
  61. package/src/slist/basics.d.ts +47 -0
  62. package/src/slist/basics.js +23 -8
  63. package/src/slist/core.d.ts +251 -0
  64. package/src/slist/core.js +151 -6
  65. package/src/slist/ext-value.d.ts +188 -0
  66. package/src/slist/ext-value.js +35 -6
  67. package/src/slist/ext.d.ts +182 -0
  68. package/src/slist/ext.js +114 -12
  69. package/src/slist/nodes.d.ts +361 -0
  70. package/src/slist/nodes.js +156 -3
  71. package/src/slist/ptr.d.ts +73 -0
  72. package/src/slist/ptr.js +45 -2
  73. package/src/slist/value.d.ts +246 -0
  74. package/src/slist/value.js +38 -6
  75. package/src/slist.d.ts +3 -0
  76. package/src/slist.js +0 -2
  77. package/src/stack.d.ts +59 -0
  78. package/src/stack.js +29 -3
  79. package/src/tree/splay-tree.d.ts +151 -0
  80. package/src/tree/splay-tree.js +94 -3
  81. package/src/value-list.d.ts +3 -0
  82. package/src/value-list.js +0 -2
  83. package/src/value-slist.d.ts +3 -0
  84. package/src/value-slist.js +0 -2
  85. package/cjs/cache/cache-fifo.js +0 -37
  86. package/cjs/cache/cache-lfu.js +0 -76
  87. package/cjs/cache/cache-lru.js +0 -100
  88. package/cjs/cache/cache-random.js +0 -77
  89. package/cjs/cache/decorator.js +0 -47
  90. package/cjs/cache.js +0 -27
  91. package/cjs/ext-list.js +0 -21
  92. package/cjs/ext-slist.js +0 -21
  93. package/cjs/ext-value-list.js +0 -21
  94. package/cjs/ext-value-slist.js +0 -21
  95. package/cjs/heap/basics.js +0 -63
  96. package/cjs/heap/leftist-heap.js +0 -124
  97. package/cjs/heap/min-heap.js +0 -294
  98. package/cjs/heap/skew-heap.js +0 -114
  99. package/cjs/heap.js +0 -21
  100. package/cjs/list/basics.js +0 -88
  101. package/cjs/list/core.js +0 -305
  102. package/cjs/list/ext-value.js +0 -88
  103. package/cjs/list/ext.js +0 -356
  104. package/cjs/list/nodes.js +0 -240
  105. package/cjs/list/ptr.js +0 -61
  106. package/cjs/list/value.js +0 -99
  107. package/cjs/list-helpers.js +0 -91
  108. package/cjs/list-utils.js +0 -141
  109. package/cjs/list.js +0 -21
  110. package/cjs/meta-utils.js +0 -171
  111. package/cjs/nt-utils.js +0 -132
  112. package/cjs/package.json +0 -1
  113. package/cjs/queue.js +0 -58
  114. package/cjs/slist/basics.js +0 -71
  115. package/cjs/slist/core.js +0 -362
  116. package/cjs/slist/ext-value.js +0 -82
  117. package/cjs/slist/ext.js +0 -336
  118. package/cjs/slist/nodes.js +0 -276
  119. package/cjs/slist/ptr.js +0 -87
  120. package/cjs/slist/value.js +0 -90
  121. package/cjs/slist.js +0 -21
  122. package/cjs/stack.js +0 -55
  123. package/cjs/tree/splay-tree.js +0 -362
  124. package/cjs/value-list.js +0 -21
  125. package/cjs/value-slist.js +0 -21
@@ -1,7 +1,9 @@
1
- 'use strict';
2
-
3
- // useful low-level operations on singly linked lists
4
-
1
+ /**
2
+ * Extract a range of nodes from a circular SLL.
3
+ * @param {object} options - Link property names.
4
+ * @param {object} range - Range descriptor with `prevFrom` and optional `to`.
5
+ * @returns {{extracted: {prevFrom: object, to: object}, rest: object|null}} The extracted sub-list and the remaining list.
6
+ */
5
7
  export const extract = ({nextName}, {prevFrom, to = prevFrom[nextName]}) => {
6
8
  const node = prevFrom[nextName],
7
9
  next = to[nextName];
@@ -15,8 +17,12 @@ export const extract = ({nextName}, {prevFrom, to = prevFrom[nextName]}) => {
15
17
  return {extracted: {prevFrom: to, to}, rest: next === node ? null : next};
16
18
  };
17
19
 
18
- // pop(options, prev).node === extract(options, {prevFrom: prev}).prevFrom[options.nextName]
19
-
20
+ /**
21
+ * Pop a single node out of its circular SLL.
22
+ * @param {object} options - Link property names.
23
+ * @param {object} prev - The node preceding the one to pop.
24
+ * @returns {{extracted: {prevFrom: object, to: object}, rest: object|null}} The popped node descriptor and the remaining list.
25
+ */
20
26
  export const pop = ({nextName}, prev) => {
21
27
  const node = prev[nextName],
22
28
  next = node[nextName];
@@ -30,6 +36,13 @@ export const pop = ({nextName}, prev) => {
30
36
  return {extracted: {prevFrom: node, to: node}, rest: next === node ? null : next};
31
37
  };
32
38
 
39
+ /**
40
+ * Splice a range of nodes into a circular SLL after a target node.
41
+ * @param {object} options - Link property names.
42
+ * @param {object} target - Node after which to insert.
43
+ * @param {object} range - Range descriptor with `prevFrom` and optional `to`.
44
+ * @returns {object} The target node.
45
+ */
33
46
  export const splice = ({nextName}, target, {prevFrom, to = prevFrom[nextName]}) => {
34
47
  // form the combined head
35
48
  const next = target[nextName];
@@ -42,6 +55,8 @@ export const splice = ({nextName}, target, {prevFrom, to = prevFrom[nextName]})
42
55
  return target;
43
56
  };
44
57
 
45
- // append(options, target, range) === splice(options, target, extract(options, range))
46
-
58
+ /**
59
+ * Alias for {@link splice}. Extract a range and splice it after a target node.
60
+ * @type {typeof splice}
61
+ */
47
62
  export const append = splice;
@@ -0,0 +1,251 @@
1
+ import {HeadNode, PtrBase, ExtListBase, SllOptions, SllRange, SllPtrRange} from './nodes.js';
2
+ import {Ptr} from './ptr.js';
3
+
4
+ /** Hosted node-based singly linked list. */
5
+ export class SList<T extends object = object> extends HeadNode {
6
+ /** The first node after the head. */
7
+ get front(): T;
8
+
9
+ /** The last node in the list. */
10
+ get back(): T;
11
+
12
+ /** A range spanning all nodes, or `null` if empty. */
13
+ get range(): SllRange<T> | null;
14
+
15
+ /** Pointer to the first node. */
16
+ get frontPtr(): Ptr<T>;
17
+
18
+ /** A pointer-based range spanning all nodes, or `null` if empty. */
19
+ get ptrRange(): SllPtrRange<T> | null;
20
+
21
+ /**
22
+ * Create a pointer to a node in this list.
23
+ * @param node - Target node, or `undefined` for the front.
24
+ * @returns A new Ptr.
25
+ */
26
+ makePtr(node?: T): Ptr<T>;
27
+
28
+ /**
29
+ * Create a pointer to the node after `prev`.
30
+ * @param prev - Preceding node, or `undefined` for the front.
31
+ * @returns A new Ptr.
32
+ */
33
+ makePtrFromPrev(prev?: T): Ptr<T>;
34
+
35
+ /**
36
+ * Remove and return the front node.
37
+ * @returns The removed node, or `undefined` if empty.
38
+ */
39
+ popFrontNode(): T | undefined;
40
+
41
+ /** Alias for {@link popFrontNode}. */
42
+ popFront(): T | undefined;
43
+
44
+ /** Alias for {@link popFrontNode}. */
45
+ pop(): T | undefined;
46
+
47
+ /**
48
+ * Insert a value at the front.
49
+ * @param value - Node or value to insert.
50
+ * @returns A Ptr to the front.
51
+ */
52
+ pushFront(value: T | PtrBase<T>): Ptr<T>;
53
+
54
+ /** Alias for {@link pushFront}. */
55
+ push(value: T | PtrBase<T>): Ptr<T>;
56
+
57
+ /**
58
+ * Insert a value at the back.
59
+ * @param value - Node or value to insert.
60
+ * @returns A Ptr to the inserted node.
61
+ */
62
+ pushBack(value: T | PtrBase<T>): Ptr<T>;
63
+
64
+ /**
65
+ * Insert an existing node at the front.
66
+ * @param nodeOrPtr - Node or pointer to insert.
67
+ * @returns A Ptr to the front.
68
+ */
69
+ pushFrontNode(nodeOrPtr: T | PtrBase<T>): Ptr<T>;
70
+
71
+ /**
72
+ * Insert an existing node at the back.
73
+ * @param nodeOrPtr - Node or pointer to insert.
74
+ * @returns A Ptr to the inserted node.
75
+ */
76
+ pushBackNode(nodeOrPtr: T | PtrBase<T>): Ptr<T>;
77
+
78
+ /**
79
+ * Move all nodes from another list to the front.
80
+ * @param list - Compatible list to consume.
81
+ * @returns A Ptr to the new front.
82
+ */
83
+ appendFront(list: HeadNode): Ptr<T>;
84
+
85
+ /**
86
+ * Move all nodes from another list to the back.
87
+ * @param list - Compatible list to consume.
88
+ * @returns A Ptr to the first appended node.
89
+ */
90
+ appendBack(list: HeadNode): Ptr<T>;
91
+
92
+ /** Alias for {@link appendBack}. */
93
+ append(list: HeadNode): Ptr<T>;
94
+
95
+ /**
96
+ * Move a pointed-to node to the front.
97
+ * @param ptr - Pointer to the node to move.
98
+ * @returns A Ptr to the front, or `this` if at head.
99
+ */
100
+ moveToFront(ptr: PtrBase<T>): Ptr<T> | this;
101
+
102
+ /**
103
+ * Move a pointed-to node to the back.
104
+ * @param ptr - Pointer to the node to move.
105
+ * @returns A Ptr to the back, or `this` if at head.
106
+ */
107
+ moveToBack(ptr: PtrBase<T>): Ptr<T> | this;
108
+
109
+ /**
110
+ * Remove all nodes.
111
+ * @param drop - If `true`, make each removed node stand-alone.
112
+ * @returns `this` for chaining.
113
+ */
114
+ clear(drop?: boolean): this;
115
+
116
+ /**
117
+ * Remove a node via its pointer.
118
+ * @param ptr - Pointer to the node to remove.
119
+ * @returns The removed node, or `null` if at head.
120
+ */
121
+ removeNode(ptr: PtrBase<T>): T | null;
122
+
123
+ /**
124
+ * Remove a pointer-based range and optionally drop nodes.
125
+ * @param ptrRange - Range to remove.
126
+ * @param drop - If `true`, make each removed node stand-alone.
127
+ * @returns A new SList containing the removed nodes.
128
+ */
129
+ removeRange(ptrRange?: SllPtrRange<T>, drop?: boolean): SList<T>;
130
+
131
+ /**
132
+ * Extract a pointer-based range into a new list.
133
+ * @param ptrRange - Range to extract (defaults to the whole list).
134
+ * @returns A new SList containing the extracted nodes.
135
+ */
136
+ extractRange(ptrRange?: SllPtrRange<T>): SList<T>;
137
+
138
+ /**
139
+ * Extract nodes that satisfy a condition into a new list.
140
+ * @param condition - Predicate receiving each node.
141
+ * @returns A new SList containing the extracted nodes.
142
+ */
143
+ extractBy(condition: (node: T) => boolean): SList<T>;
144
+
145
+ /**
146
+ * Reverse the order of all nodes in place.
147
+ * @returns `this` for chaining.
148
+ */
149
+ reverse(): this;
150
+
151
+ /**
152
+ * Sort nodes in place using merge sort.
153
+ * @param lessFn - Returns `true` if `a` should precede `b`.
154
+ * @returns `this` for chaining.
155
+ */
156
+ sort(lessFn: (a: T, b: T) => boolean): this;
157
+
158
+ /**
159
+ * Detach all nodes as a pointer range.
160
+ * @returns A pointer range, or `null` if empty.
161
+ */
162
+ releaseAsPtrRange(): SllPtrRange<T> | null;
163
+
164
+ /**
165
+ * Detach all nodes as a raw circular list.
166
+ * @returns Head of the raw circular list, or `null` if empty.
167
+ */
168
+ releaseRawList(): T | null;
169
+
170
+ /**
171
+ * Detach all nodes as a null-terminated list.
172
+ * @returns Object with `head` and `tail`, or `null` if empty.
173
+ */
174
+ releaseNTList(): { head: T; tail: T } | null;
175
+
176
+ /**
177
+ * Validate that a range is reachable within this list.
178
+ * @param range - Range to validate.
179
+ * @returns `true` if the range is valid.
180
+ */
181
+ validateRange(range?: SllRange<T>): boolean;
182
+
183
+ /** Iterate over nodes from front to back. */
184
+ [Symbol.iterator](): IterableIterator<T>;
185
+
186
+ /**
187
+ * Get an iterable over nodes in a range.
188
+ * @param range - Sub-range to iterate.
189
+ * @returns An iterable iterator of nodes.
190
+ */
191
+ getNodeIterator(range?: SllRange<T>): IterableIterator<T>;
192
+
193
+ /** Alias for {@link getNodeIterator}. */
194
+ getIterator(range?: SllRange<T>): IterableIterator<T>;
195
+
196
+ /**
197
+ * Get an iterable of Ptr objects over a pointer range.
198
+ * @param ptrRange - Sub-range to iterate.
199
+ * @returns An iterable iterator of Ptrs.
200
+ */
201
+ getPtrIterator(ptrRange?: SllPtrRange<T>): IterableIterator<Ptr<T>>;
202
+
203
+ /**
204
+ * Create an empty list with the same options.
205
+ * @returns A new empty SList.
206
+ */
207
+ make(): SList<T>;
208
+
209
+ /**
210
+ * Create a list from values with the same options.
211
+ * @param values - Iterable of node objects.
212
+ * @returns A new SList.
213
+ */
214
+ makeFrom(values: Iterable<T>): SList<T>;
215
+
216
+ /**
217
+ * Create a list from a range with the same options.
218
+ * @param range - Range to copy.
219
+ * @returns A new SList.
220
+ */
221
+ makeFromRange(range: SllRange<T>): SList<T>;
222
+
223
+ /**
224
+ * Build an SList from an iterable of node objects.
225
+ * @param values - Iterable of nodes.
226
+ * @param options - Link property names.
227
+ * @returns A new SList.
228
+ */
229
+ static from<T extends object = object>(values: Iterable<T>, options?: SllOptions): SList<T>;
230
+
231
+ /**
232
+ * Build an SList from a pointer range.
233
+ * @param ptrRange - Pointer range to copy.
234
+ * @param options - Link property names.
235
+ * @returns A new SList.
236
+ */
237
+ static fromPtrRange<T extends object = object>(ptrRange: SllPtrRange<T>, options?: SllOptions): SList<T>;
238
+
239
+ /**
240
+ * Build an SList from an external list, consuming it.
241
+ * @param extList - External list to consume.
242
+ * @returns A new SList.
243
+ */
244
+ static fromExtList<T extends object = object>(extList: ExtListBase<T>): SList<T>;
245
+
246
+ /** The Ptr class associated with this list type. */
247
+ static Ptr: typeof Ptr;
248
+ }
249
+
250
+ export { Ptr };
251
+ export default SList;
package/src/slist/core.js CHANGED
@@ -1,29 +1,44 @@
1
- 'use strict';
2
-
3
1
  import {addAliases, normalizeIterator} from '../meta-utils.js';
4
2
  import {ExtListBase, HeadNode} from './nodes.js';
5
3
  import {append} from './basics.js';
6
4
  import Ptr from './ptr.js';
7
5
 
6
+ /** Hosted node-based singly linked list with a sentinel head. */
8
7
  export class SList extends HeadNode {
8
+ /** Pointer to the first node. */
9
9
  get frontPtr() {
10
10
  return new Ptr(this);
11
11
  }
12
12
 
13
+ /** A pointer-based range spanning all nodes, or `null` if empty. */
13
14
  get ptrRange() {
14
15
  return this.isEmpty ? null : {from: new Ptr(this), to: this.last};
15
16
  }
16
17
 
18
+ /**
19
+ * Create a pointer to a node in this list.
20
+ * @param {object} [node] - Target node, or `undefined` for the front.
21
+ * @returns {Ptr} A new Ptr.
22
+ */
17
23
  makePtr(node) {
18
24
  if (node && !this.isNodeLike(node)) throw new Error('"node" is not a compatible node');
19
25
  return new Ptr(this, node);
20
26
  }
21
27
 
28
+ /**
29
+ * Create a pointer to the node after `prev`.
30
+ * @param {object} [prev] - Preceding node, or `undefined` for the head.
31
+ * @returns {Ptr} A new Ptr.
32
+ */
22
33
  makePtrFromPrev(prev) {
23
34
  if (prev && !this.isNodeLike(prev)) throw new Error('"prev" is not a compatible node');
24
35
  return new Ptr(this, null, prev || this);
25
36
  }
26
37
 
38
+ /**
39
+ * Remove and return the front node.
40
+ * @returns {object|undefined} The removed node, or `undefined` if empty.
41
+ */
27
42
  popFrontNode() {
28
43
  if (this[this.nextName] === this) return undefined;
29
44
  const node = this[this.nextName];
@@ -32,6 +47,11 @@ export class SList extends HeadNode {
32
47
  return (node[this.nextName] = node);
33
48
  }
34
49
 
50
+ /**
51
+ * Insert a value at the front.
52
+ * @param {*} value - Node or value to insert.
53
+ * @returns {Ptr} A Ptr to the front.
54
+ */
35
55
  pushFront(value) {
36
56
  const node = this.adoptValue(value);
37
57
  node[this.nextName] = this[this.nextName];
@@ -40,6 +60,11 @@ export class SList extends HeadNode {
40
60
  return this.makePtr();
41
61
  }
42
62
 
63
+ /**
64
+ * Insert a value at the back.
65
+ * @param {*} value - Node or value to insert.
66
+ * @returns {Ptr} A Ptr to the inserted node.
67
+ */
43
68
  pushBack(value) {
44
69
  const node = this.adoptValue(value);
45
70
  node[this.nextName] = this;
@@ -48,6 +73,11 @@ export class SList extends HeadNode {
48
73
  return this.makePtrFromPrev(last);
49
74
  }
50
75
 
76
+ /**
77
+ * Insert an existing node at the front.
78
+ * @param {object} nodeOrPtr - Node or pointer to insert.
79
+ * @returns {Ptr} A Ptr to the front.
80
+ */
51
81
  pushFrontNode(nodeOrPtr) {
52
82
  const node = this.adoptNode(nodeOrPtr);
53
83
  node[this.nextName] = this[this.nextName];
@@ -56,6 +86,11 @@ export class SList extends HeadNode {
56
86
  return this.makePtr();
57
87
  }
58
88
 
89
+ /**
90
+ * Insert an existing node at the back.
91
+ * @param {object} nodeOrPtr - Node or pointer to insert.
92
+ * @returns {Ptr} A Ptr to the inserted node.
93
+ */
59
94
  pushBackNode(nodeOrPtr) {
60
95
  const node = this.adoptNode(nodeOrPtr);
61
96
  node[this.nextName] = this;
@@ -64,6 +99,11 @@ export class SList extends HeadNode {
64
99
  return this.makePtrFromPrev(last);
65
100
  }
66
101
 
102
+ /**
103
+ * Move all nodes from another list to the front.
104
+ * @param {HeadNode} list - Compatible list to consume.
105
+ * @returns {Ptr} A Ptr to the new front.
106
+ */
67
107
  appendFront(list) {
68
108
  if (!this.isCompatible(list)) throw new Error('Incompatible lists');
69
109
  if (list.isEmpty) return this;
@@ -76,6 +116,11 @@ export class SList extends HeadNode {
76
116
  return this.makePtr();
77
117
  }
78
118
 
119
+ /**
120
+ * Move all nodes from another list to the back.
121
+ * @param {HeadNode} list - Compatible list to consume.
122
+ * @returns {Ptr} A Ptr to the first appended node.
123
+ */
79
124
  appendBack(list) {
80
125
  if (!this.isCompatible(list)) throw new Error('Incompatible lists');
81
126
  if (list.isEmpty) return this;
@@ -90,6 +135,11 @@ export class SList extends HeadNode {
90
135
  return this.makePtrFromPrev(last);
91
136
  }
92
137
 
138
+ /**
139
+ * Move a node (identified by pointer) to the front.
140
+ * @param {Ptr} ptr - Pointer to the node to move.
141
+ * @returns {Ptr|SList} A Ptr to the front, or `this` if at head.
142
+ */
93
143
  moveToFront(ptr) {
94
144
  if (!this.isCompatiblePtr(ptr)) throw new Error('Incompatible pointer');
95
145
  ptr.list = this;
@@ -99,6 +149,11 @@ export class SList extends HeadNode {
99
149
  return this.pushFrontNode(node);
100
150
  }
101
151
 
152
+ /**
153
+ * Move a node (identified by pointer) to the back.
154
+ * @param {Ptr} ptr - Pointer to the node to move.
155
+ * @returns {Ptr|SList} A Ptr to the back, or `this` if at head.
156
+ */
102
157
  moveToBack(ptr) {
103
158
  if (!this.isCompatiblePtr(ptr)) throw new Error('Incompatible pointer');
104
159
  ptr.list = this;
@@ -108,6 +163,11 @@ export class SList extends HeadNode {
108
163
  return this.pushBackNode(node);
109
164
  }
110
165
 
166
+ /**
167
+ * Remove all nodes.
168
+ * @param {boolean} [drop] - If `true`, make each removed node stand-alone.
169
+ * @returns {SList} `this` for chaining.
170
+ */
111
171
  clear(drop) {
112
172
  if (drop) {
113
173
  let current = this;
@@ -123,6 +183,11 @@ export class SList extends HeadNode {
123
183
  return this;
124
184
  }
125
185
 
186
+ /**
187
+ * Remove the node at a pointer position.
188
+ * @param {Ptr} ptr - Pointer whose current node to remove.
189
+ * @returns {object|null} The removed node, or `null` if at head.
190
+ */
126
191
  removeNode(ptr) {
127
192
  if (!ptr.isPrevNodeValid()) throw new Error('Cannot remove node: "prevNode" is invalid');
128
193
  if (!this.isCompatiblePtr(ptr)) throw new Error('Incompatible pointer');
@@ -135,10 +200,21 @@ export class SList extends HeadNode {
135
200
  return node;
136
201
  }
137
202
 
203
+ /**
204
+ * Remove a pointer-based range and optionally drop nodes.
205
+ * @param {object} [ptrRange] - Range to remove.
206
+ * @param {boolean} [drop] - If `true`, make each removed node stand-alone.
207
+ * @returns {SList} A new SList containing the removed nodes.
208
+ */
138
209
  removeRange(ptrRange, drop) {
139
210
  return this.extractRange(ptrRange).clear(drop);
140
211
  }
141
212
 
213
+ /**
214
+ * Extract a pointer-based range into a new list.
215
+ * @param {object} [ptrRange={}] - Range to extract (defaults to the whole list).
216
+ * @returns {SList} A new SList containing the extracted nodes.
217
+ */
142
218
  extractRange(ptrRange = {}) {
143
219
  const originalTo = ptrRange.to;
144
220
  ptrRange = this.normalizePtrRange(ptrRange.from ? ptrRange : {...ptrRange, from: this.frontPtr});
@@ -156,6 +232,11 @@ export class SList extends HeadNode {
156
232
  return extracted;
157
233
  }
158
234
 
235
+ /**
236
+ * Extract nodes that satisfy a condition into a new list.
237
+ * @param {Function} condition - Predicate receiving each node.
238
+ * @returns {SList} A new SList containing the extracted nodes.
239
+ */
159
240
  extractBy(condition) {
160
241
  const extracted = this.make();
161
242
  if (this.isEmpty) return extracted;
@@ -170,6 +251,10 @@ export class SList extends HeadNode {
170
251
  return extracted;
171
252
  }
172
253
 
254
+ /**
255
+ * Reverse the order of all nodes in place.
256
+ * @returns {SList} `this` for chaining.
257
+ */
173
258
  reverse() {
174
259
  if (this.isOneOrEmpty) return this;
175
260
  this.last = this[this.nextName];
@@ -185,6 +270,11 @@ export class SList extends HeadNode {
185
270
  return this;
186
271
  }
187
272
 
273
+ /**
274
+ * Sort nodes in place using merge sort.
275
+ * @param {Function} lessFn - Returns `true` if `a` should precede `b`.
276
+ * @returns {SList} `this` for chaining.
277
+ */
188
278
  sort(lessFn) {
189
279
  if (this.isOneOrEmpty) return this;
190
280
 
@@ -211,6 +301,10 @@ export class SList extends HeadNode {
211
301
  return this;
212
302
  }
213
303
 
304
+ /**
305
+ * Detach all nodes as a pointer range.
306
+ * @returns {object|null} A pointer range, or `null` if empty.
307
+ */
214
308
  releaseAsPtrRange() {
215
309
  if (this.isEmpty) return null;
216
310
  const head = this[this.nextName],
@@ -220,6 +314,10 @@ export class SList extends HeadNode {
220
314
  return {from: new Ptr(this, null, tail), to: tail};
221
315
  }
222
316
 
317
+ /**
318
+ * Detach all nodes as a raw circular list.
319
+ * @returns {object|null} Head of the raw circular list, or `null` if empty.
320
+ */
223
321
  releaseRawList() {
224
322
  if (this.isEmpty) return null;
225
323
  const head = this[this.nextName],
@@ -229,6 +327,10 @@ export class SList extends HeadNode {
229
327
  return head;
230
328
  }
231
329
 
330
+ /**
331
+ * Detach all nodes as a null-terminated list.
332
+ * @returns {{head: object, tail: object}|null} Object with `head` and `tail`, or `null` if empty.
333
+ */
232
334
  releaseNTList() {
233
335
  if (this.isEmpty) return null;
234
336
  const head = this[this.nextName],
@@ -238,6 +340,11 @@ export class SList extends HeadNode {
238
340
  return {head, tail};
239
341
  }
240
342
 
343
+ /**
344
+ * Validate that a range is reachable within this list.
345
+ * @param {object} [range={}] - Range to validate.
346
+ * @returns {boolean} `true` if the range is valid.
347
+ */
241
348
  validateRange(range = {}) {
242
349
  range = this.normalizeRange(range);
243
350
  let current = range.from;
@@ -248,8 +355,7 @@ export class SList extends HeadNode {
248
355
  return true;
249
356
  }
250
357
 
251
- // iterators
252
-
358
+ /** Iterate over nodes from front to back. */
253
359
  [Symbol.iterator]() {
254
360
  let current = this[this.nextName],
255
361
  readyToStop = this.isEmpty;
@@ -264,6 +370,11 @@ export class SList extends HeadNode {
264
370
  });
265
371
  }
266
372
 
373
+ /**
374
+ * Get an iterable over nodes in a range.
375
+ * @param {object} [range={}] - Sub-range to iterate.
376
+ * @returns {Iterable} An iterable iterator of nodes.
377
+ */
267
378
  getNodeIterator(range = {}) {
268
379
  range = this.normalizeRange(range);
269
380
  const {from, to} = range;
@@ -285,6 +396,11 @@ export class SList extends HeadNode {
285
396
  };
286
397
  }
287
398
 
399
+ /**
400
+ * Get an iterable of Ptr objects over a pointer range.
401
+ * @param {object} [ptrRange={}] - Sub-range to iterate.
402
+ * @returns {Iterable} An iterable iterator of Ptrs.
403
+ */
288
404
  getPtrIterator(ptrRange = {}) {
289
405
  if (!ptrRange.from) ptrRange = Object.assign({from: this.frontPtr}, ptrRange);
290
406
  ptrRange = this.normalizePtrRange(ptrRange);
@@ -307,26 +423,50 @@ export class SList extends HeadNode {
307
423
  };
308
424
  }
309
425
 
310
- // meta helpers
311
-
426
+ /**
427
+ * Create an empty list with the same options.
428
+ * @returns {SList} A new empty SList.
429
+ */
312
430
  make() {
313
431
  return new SList(this);
314
432
  }
315
433
 
434
+ /**
435
+ * Create a list from values with the same options.
436
+ * @param {Iterable} values - Iterable of node objects.
437
+ * @returns {SList} A new SList.
438
+ */
316
439
  makeFrom(values) {
317
440
  return SList.from(values, this);
318
441
  }
319
442
 
443
+ /**
444
+ * Create a list from a range with the same options.
445
+ * @param {object} range - Range to copy.
446
+ * @returns {SList} A new SList.
447
+ */
320
448
  makeFromRange(range) {
321
449
  return SList.fromRange(range, this);
322
450
  }
323
451
 
452
+ /**
453
+ * Build an SList from an iterable of node objects.
454
+ * @param {Iterable} values - Iterable of nodes.
455
+ * @param {object} [options] - Link property names.
456
+ * @returns {SList} A new SList.
457
+ */
324
458
  static from(values, options) {
325
459
  const list = new SList(options);
326
460
  for (const value of values) list.pushBack(value);
327
461
  return list;
328
462
  }
329
463
 
464
+ /**
465
+ * Build an SList from a pointer range.
466
+ * @param {object} ptrRange - Pointer range to copy.
467
+ * @param {object} [options] - Link property names.
468
+ * @returns {SList} A new SList.
469
+ */
330
470
  static fromPtrRange(ptrRange, options) {
331
471
  const list = new SList(options);
332
472
  if (!list.isCompatiblePtrRange(ptrRange)) throw new Error('"range" is not a compatible range');
@@ -334,6 +474,11 @@ export class SList extends HeadNode {
334
474
  return list;
335
475
  }
336
476
 
477
+ /**
478
+ * Build an SList from an external list, consuming it.
479
+ * @param {ExtListBase} extList - External list to consume.
480
+ * @returns {SList} A new SList.
481
+ */
337
482
  static fromExtList(extList) {
338
483
  if (!(extList instanceof ExtListBase)) throw new Error('Not a circular list');
339
484