list-toolkit 2.2.6 → 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 -37
  2. package/llms-full.txt +743 -0
  3. package/llms.txt +100 -0
  4. package/package.json +34 -29
  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
@@ -0,0 +1,336 @@
1
+ /** Options for configuring link property names. */
2
+ export interface DllOptions {
3
+ /** Name of the "next" link property. */
4
+ nextName?: string;
5
+ /** Name of the "prev" link property. */
6
+ prevName?: string;
7
+ }
8
+
9
+ /** A range defined by two nodes. */
10
+ export interface DllRange<T extends object = object> {
11
+ /** Start node of the range. */
12
+ from?: T;
13
+ /** End node of the range. */
14
+ to?: T;
15
+ /** List that owns the range. */
16
+ list?: HeadNode | ExtListBase<T>;
17
+ }
18
+
19
+ /** A range defined by a pointer and a node. */
20
+ export interface DllPtrRange<T extends object = object> {
21
+ /** Start pointer of the range. */
22
+ from?: PtrBase<T>;
23
+ /** End node of the range. */
24
+ to?: T;
25
+ /** List that owns the range. */
26
+ list?: HeadNode | ExtListBase<T>;
27
+ }
28
+
29
+ /**
30
+ * Check whether a node has both link properties set.
31
+ * @param options - Link property names.
32
+ * @param node - Object to test.
33
+ * @returns `true` if the node has both next and prev links.
34
+ */
35
+ export function isNodeLike<T extends object>(options: DllOptions, node: T | null | undefined): boolean;
36
+
37
+ /**
38
+ * Check whether a node links to itself on both sides.
39
+ * @param options - Link property names.
40
+ * @param node - Object to test.
41
+ * @returns `true` if the node is stand-alone (self-linked).
42
+ */
43
+ export function isStandAlone<T extends object>(options: DllOptions, node: T | null | undefined): boolean;
44
+
45
+ /**
46
+ * Check whether two option sets share the same link property names.
47
+ * @param options1 - First set of options.
48
+ * @param options2 - Second set of options.
49
+ * @returns `true` if nextName and prevName match.
50
+ */
51
+ export function isCompatible(options1: DllOptions, options2: DllOptions): boolean;
52
+
53
+ /** A self-linked circular DLL node. */
54
+ export class Node {
55
+ /** Name of the "next" link property. */
56
+ readonly nextName: string;
57
+ /** Name of the "prev" link property. */
58
+ readonly prevName: string;
59
+
60
+ /** @param options - Link property names. */
61
+ constructor(options?: DllOptions);
62
+
63
+ /** Whether this node links to itself. */
64
+ get isStandAlone(): boolean;
65
+ }
66
+
67
+ /** Sentinel node used as the head of a hosted DLL. */
68
+ export class HeadNode extends Node {
69
+ /**
70
+ * Test whether a value looks like a compatible node.
71
+ * @param node - Object to test.
72
+ * @returns `true` if the object has valid next and prev links.
73
+ */
74
+ isNodeLike<T extends object>(node: T | null | undefined): boolean;
75
+
76
+ /**
77
+ * Test whether an options object shares the same link names.
78
+ * @param options - Options to compare.
79
+ * @returns `true` if names match.
80
+ */
81
+ isCompatibleNames(options: DllOptions): boolean;
82
+
83
+ /**
84
+ * Test whether another list is compatible.
85
+ * @param list - List or head node to compare.
86
+ * @returns `true` if compatible.
87
+ */
88
+ isCompatible(list: HeadNode | ExtListBase): boolean;
89
+
90
+ /**
91
+ * Test whether a pointer belongs to a compatible list.
92
+ * @param ptr - Pointer to test.
93
+ * @returns `true` if compatible.
94
+ */
95
+ isCompatiblePtr(ptr: PtrBase): boolean;
96
+
97
+ /**
98
+ * Test whether a range is compatible with this list.
99
+ * @param range - Range to test.
100
+ * @returns `true` if compatible.
101
+ */
102
+ isCompatibleRange(range: DllRange | null): boolean;
103
+
104
+ /** Whether the list is empty (head links to itself). */
105
+ get isEmpty(): boolean;
106
+
107
+ /** Whether the list contains exactly one node. */
108
+ get isOne(): boolean;
109
+
110
+ /** Whether the list contains zero or one nodes. */
111
+ get isOneOrEmpty(): boolean;
112
+
113
+ /** The sentinel head node. */
114
+ get head(): this;
115
+
116
+ /** The first node after the head. */
117
+ get front(): object;
118
+
119
+ /** The last node before the head. */
120
+ get back(): object;
121
+
122
+ /** A range spanning all nodes, or `null` if empty. */
123
+ get range(): DllRange | null;
124
+
125
+ /**
126
+ * Count the number of nodes in the list.
127
+ * @returns Node count.
128
+ */
129
+ getLength(): number;
130
+
131
+ /**
132
+ * Adopt a node or pointer into this list, making it stand-alone if needed.
133
+ * @param nodeOrPtr - Node or pointer to adopt.
134
+ * @returns The adopted node.
135
+ * @throws If the node is already part of another list.
136
+ */
137
+ adoptNode<T extends object>(nodeOrPtr: T | PtrBase<T>): T;
138
+
139
+ /**
140
+ * Adopt a value into this list. Overridden by value-list subclasses.
141
+ * @param nodeOrPtr - Node, pointer, or value to adopt.
142
+ * @returns The adopted node.
143
+ */
144
+ adoptValue(nodeOrPtr: any): any;
145
+
146
+ /**
147
+ * Normalize a node or pointer to a plain node.
148
+ * @param nodeOrPtr - Node or pointer.
149
+ * @returns The underlying node, or `null`.
150
+ */
151
+ normalizeNode<T extends object>(nodeOrPtr: T | PtrBase<T> | null): T | null;
152
+
153
+ /**
154
+ * Normalize a range, resolving any pointers to nodes.
155
+ * @param range - Range to normalize.
156
+ * @returns Normalized range with plain node references.
157
+ */
158
+ normalizeRange<T extends object>(range: DllRange<T>): DllRange<T>;
159
+ }
160
+
161
+ /** A node that wraps an arbitrary value. */
162
+ export class ValueNode<V = unknown> extends Node {
163
+ /** The wrapped value. */
164
+ value: V;
165
+
166
+ /**
167
+ * @param value - Value to wrap.
168
+ * @param options - Link property names.
169
+ */
170
+ constructor(value: V, options?: DllOptions);
171
+ }
172
+
173
+ /** Base class for DLL pointers. */
174
+ export class PtrBase<T extends object = object> {
175
+ /** The list this pointer belongs to. */
176
+ list: HeadNode | ExtListBase<T>;
177
+ /** The node this pointer references. */
178
+ node: T;
179
+
180
+ /**
181
+ * @param list - Owning list, or another pointer to copy.
182
+ * @param node - Target node or pointer.
183
+ * @param ListClass - Expected list constructor for validation.
184
+ */
185
+ constructor(list: HeadNode | ExtListBase<T> | PtrBase<T>, node?: T | PtrBase<T>, ListClass?: Function);
186
+
187
+ /** The node after the current node. */
188
+ get nextNode(): T;
189
+
190
+ /** The node before the current node. */
191
+ get prevNode(): T;
192
+
193
+ /**
194
+ * Whether the previous node is valid for iteration.
195
+ * @returns Always `true` for DLL pointers.
196
+ */
197
+ isPrevNodeValid(): boolean;
198
+
199
+ /**
200
+ * Advance the pointer to the next node.
201
+ * @returns `this` for chaining.
202
+ */
203
+ next(): this;
204
+
205
+ /**
206
+ * Move the pointer to the previous node.
207
+ * @returns `this` for chaining.
208
+ */
209
+ prev(): this;
210
+ }
211
+
212
+ /** Base class for external (headless) DLL wrappers. */
213
+ export class ExtListBase<T extends object = object> {
214
+ /** Name of the "next" link property. */
215
+ readonly nextName: string;
216
+ /** Name of the "prev" link property. */
217
+ readonly prevName: string;
218
+ /** Current head node, or `null` if empty. */
219
+ head: T | null;
220
+
221
+ /**
222
+ * @param head - Initial head node, pointer, or another ExtListBase to copy.
223
+ * @param options - Link property names.
224
+ */
225
+ constructor(head?: T | PtrBase<T> | ExtListBase<T> | null, options?: DllOptions);
226
+
227
+ /**
228
+ * Test whether another list is compatible.
229
+ * @param list - List to compare.
230
+ * @returns `true` if compatible.
231
+ */
232
+ isCompatible(list: HeadNode | ExtListBase): boolean;
233
+
234
+ /**
235
+ * Test whether a pointer belongs to a compatible list.
236
+ * @param ptr - Pointer to test.
237
+ * @returns `true` if compatible.
238
+ */
239
+ isCompatiblePtr(ptr: PtrBase): boolean;
240
+
241
+ // Copied from HeadNode via copyDescriptors:
242
+
243
+ /**
244
+ * Test whether a value looks like a compatible node.
245
+ * @param node - Object to test.
246
+ * @returns `true` if the object has valid next and prev links.
247
+ */
248
+ isNodeLike(node: object | null | undefined): boolean;
249
+
250
+ /**
251
+ * Test whether an options object shares the same link names.
252
+ * @param options - Options to compare.
253
+ * @returns `true` if names match.
254
+ */
255
+ isCompatibleNames(options: DllOptions): boolean;
256
+
257
+ /**
258
+ * Test whether a range is compatible with this list.
259
+ * @param range - Range to test.
260
+ * @returns `true` if compatible.
261
+ */
262
+ isCompatibleRange(range: DllRange<T> | null): boolean;
263
+
264
+ /**
265
+ * Normalize a node or pointer to a plain node.
266
+ * @param nodeOrPtr - Node or pointer.
267
+ * @returns The underlying node, or `null`.
268
+ */
269
+ normalizeNode(nodeOrPtr: T | PtrBase<T> | null): T | null;
270
+
271
+ /**
272
+ * Normalize a range, resolving any pointers to nodes.
273
+ * @param range - Range to normalize.
274
+ * @returns Normalized range with plain node references.
275
+ */
276
+ normalizeRange(range: DllRange<T>): DllRange<T>;
277
+
278
+ /**
279
+ * Adopt a node or pointer into this list.
280
+ * @param nodeOrPtr - Node or pointer to adopt.
281
+ * @returns The adopted node.
282
+ */
283
+ adoptNode(nodeOrPtr: T | PtrBase<T>): T;
284
+
285
+ /** Alias for {@link adoptNode}. */
286
+ adoptValue(nodeOrPtr: T | PtrBase<T>): T;
287
+
288
+ /** Whether the list is empty. */
289
+ get isEmpty(): boolean;
290
+
291
+ /** Whether the list contains exactly one node. */
292
+ get isOne(): boolean;
293
+
294
+ /** Whether the list contains zero or one nodes. */
295
+ get isOneOrEmpty(): boolean;
296
+
297
+ /** The head node, or `undefined` if empty. */
298
+ get front(): T | undefined;
299
+
300
+ /** The node before the head, or `undefined` if empty. */
301
+ get back(): T | undefined;
302
+
303
+ /** A range spanning all nodes, or `null` if empty. */
304
+ get range(): DllRange<T> | null;
305
+
306
+ /**
307
+ * Count the number of nodes.
308
+ * @returns Node count.
309
+ */
310
+ getLength(): number;
311
+
312
+ /**
313
+ * Set a new head node.
314
+ * @param head - New head node or pointer, or `null` to detach.
315
+ * @returns The previous head node, or `null`.
316
+ */
317
+ attach(head?: T | PtrBase<T> | null): T | null;
318
+
319
+ /**
320
+ * Detach the head, leaving the list empty.
321
+ * @returns The previous head node, or `null`.
322
+ */
323
+ detach(): T | null;
324
+
325
+ /**
326
+ * Advance the head to the next node.
327
+ * @returns `this` for chaining.
328
+ */
329
+ next(): this;
330
+
331
+ /**
332
+ * Move the head to the previous node.
333
+ * @returns `this` for chaining.
334
+ */
335
+ prev(): this;
336
+ }
package/src/list/nodes.js CHANGED
@@ -1,24 +1,49 @@
1
- 'use strict';
2
-
3
1
  import {isRangeLike, normalizeNode, normalizeRange} from '../list-helpers.js';
4
2
  import {addAlias, copyDescriptors, canHaveProps} from '../meta-utils.js';
5
3
 
4
+ /**
5
+ * Check whether a node has valid next and prev links.
6
+ * @param {object} options - Link property names.
7
+ * @param {object} node - Node to check.
8
+ * @returns {boolean} `true` if the node has truthy next and prev links.
9
+ */
6
10
  export const isNodeLike = ({nextName, prevName}, node) => node && node[prevName] && node[nextName];
11
+ /**
12
+ * Check whether a node points to itself (stand-alone).
13
+ * @param {object} options - Link property names.
14
+ * @param {object} node - Node to check.
15
+ * @returns {boolean} `true` if the node's next and prev links point to itself.
16
+ */
7
17
  export const isStandAlone = ({nextName, prevName}, node) => node && node[prevName] === node && node[nextName] === node;
18
+ /**
19
+ * Check whether two option sets share the same link property names.
20
+ * @param {object} options1 - First options.
21
+ * @param {object} options2 - Second options.
22
+ * @returns {boolean} `true` if `nextName` and `prevName` match.
23
+ */
8
24
  export const isCompatible = (options1, options2) => options1.nextName === options2.nextName && options1.prevName === options2.prevName;
9
25
 
26
+ /** Doubly linked list node with circular self-links. */
10
27
  export class Node {
28
+ /** @param {object} [options] - Link property names. */
11
29
  constructor({nextName = 'next', prevName = 'prev'} = {}) {
12
30
  this.nextName = nextName;
13
31
  this.prevName = prevName;
14
32
  this[nextName] = this[prevName] = this;
15
33
  }
34
+ /** Whether this node's next link points to itself. */
16
35
  get isStandAlone() {
17
36
  return this[this.nextName] === this;
18
37
  }
19
38
  }
20
39
 
40
+ /** Sentinel head node for hosted doubly linked lists. */
21
41
  export class HeadNode extends Node {
42
+ /**
43
+ * Check whether a value looks like a compatible node.
44
+ * @param {*} node - Value to check.
45
+ * @returns {boolean} `true` if the value has valid next and prev links.
46
+ */
22
47
  isNodeLike(node) {
23
48
  if (!node) return false;
24
49
  const next = node[this.nextName];
@@ -27,14 +52,29 @@ export class HeadNode extends Node {
27
52
  return prev && canHaveProps[typeof prev] === 1;
28
53
  }
29
54
 
55
+ /**
56
+ * Check whether another options object shares the same link names.
57
+ * @param {object} options - Options to compare.
58
+ * @returns {boolean} `true` if `nextName` and `prevName` match.
59
+ */
30
60
  isCompatibleNames({nextName, prevName}) {
31
61
  return this.nextName === nextName && this.prevName === prevName;
32
62
  }
33
63
 
64
+ /**
65
+ * Check whether another list is compatible with this one.
66
+ * @param {object} list - List to compare.
67
+ * @returns {boolean} `true` if compatible.
68
+ */
34
69
  isCompatible(list) {
35
70
  return list === this || (list instanceof HeadNode && this.nextName === list.nextName && this.prevName === list.prevName);
36
71
  }
37
72
 
73
+ /**
74
+ * Check whether a pointer belongs to a compatible list.
75
+ * @param {PtrBase} ptr - Pointer to check.
76
+ * @returns {boolean} `true` if compatible.
77
+ */
38
78
  isCompatiblePtr(ptr) {
39
79
  return (
40
80
  ptr instanceof PtrBase &&
@@ -42,38 +82,54 @@ export class HeadNode extends Node {
42
82
  );
43
83
  }
44
84
 
85
+ /**
86
+ * Check whether a range is compatible with this list.
87
+ * @param {object} [range] - Range to validate.
88
+ * @returns {boolean} `true` if compatible.
89
+ */
45
90
  isCompatibleRange(range) {
46
- return isRangeLike(this, range);
91
+ return isRangeLike(this, range, PtrBase);
47
92
  }
48
93
 
94
+ /** Whether the list has no nodes. */
49
95
  get isEmpty() {
50
96
  return this[this.nextName] === this;
51
97
  }
52
98
 
99
+ /** Whether the list has exactly one node. */
53
100
  get isOne() {
54
101
  return this[this.nextName] !== this && this[this.nextName][this.nextName] === this;
55
102
  }
56
103
 
104
+ /** Whether the list has zero or one node. */
57
105
  get isOneOrEmpty() {
58
106
  return this[this.nextName][this.nextName] === this;
59
107
  }
60
108
 
109
+ /** The head sentinel itself. */
61
110
  get head() {
62
111
  return this;
63
112
  }
64
113
 
114
+ /** The first node after the head. */
65
115
  get front() {
66
116
  return this[this.nextName];
67
117
  }
68
118
 
119
+ /** The last node before the head. */
69
120
  get back() {
70
121
  return this[this.prevName];
71
122
  }
72
123
 
124
+ /** A range spanning all nodes, or `null` if empty. */
73
125
  get range() {
74
126
  return this[this.nextName] === this ? null : {from: this[this.nextName], to: this[this.prevName], list: this};
75
127
  }
76
128
 
129
+ /**
130
+ * Count the number of nodes.
131
+ * @returns {number} The node count.
132
+ */
77
133
  getLength() {
78
134
  let n = 0;
79
135
  const nextName = this.nextName;
@@ -81,6 +137,11 @@ export class HeadNode extends Node {
81
137
  return n;
82
138
  }
83
139
 
140
+ /**
141
+ * Adopt a node or pointer, making it stand-alone if needed.
142
+ * @param {object} nodeOrPtr - Node or pointer to adopt.
143
+ * @returns {object} The adopted node.
144
+ */
84
145
  adoptNode(nodeOrPtr) {
85
146
  const node = nodeOrPtr instanceof PtrBase ? nodeOrPtr.node : nodeOrPtr;
86
147
  if (node[this.nextName] || node[this.prevName]) {
@@ -92,12 +153,22 @@ export class HeadNode extends Node {
92
153
  return node;
93
154
  }
94
155
 
156
+ /**
157
+ * Normalize a node or pointer to a plain node.
158
+ * @param {object|null} nodeOrPtr - Node or pointer.
159
+ * @returns {object|null} The underlying node, or `null`.
160
+ */
95
161
  normalizeNode(nodeOrPtr) {
96
162
  const node = normalizeNode(this, nodeOrPtr, PtrBase);
97
163
  if (nodeOrPtr instanceof PtrBase) nodeOrPtr.list = this;
98
164
  return node;
99
165
  }
100
166
 
167
+ /**
168
+ * Normalize a range, resolving any pointers to nodes.
169
+ * @param {object} [range] - Range to normalize.
170
+ * @returns {object|null} The normalized range, or `null`.
171
+ */
101
172
  normalizeRange(range) {
102
173
  return normalizeRange(this, range, PtrBase);
103
174
  }
@@ -105,14 +176,25 @@ export class HeadNode extends Node {
105
176
 
106
177
  addAlias(HeadNode.prototype, 'adoptNode', 'adoptValue');
107
178
 
179
+ /** Value wrapper node for doubly linked lists. */
108
180
  export class ValueNode extends Node {
181
+ /**
182
+ * @param {*} value - Value to wrap.
183
+ * @param {object} [options] - Link property names.
184
+ */
109
185
  constructor(value, options) {
110
186
  super(options);
111
187
  this.value = value;
112
188
  }
113
189
  }
114
190
 
191
+ /** Base class for DLL pointers providing navigation. */
115
192
  export class PtrBase {
193
+ /**
194
+ * @param {PtrBase|HeadNode|ExtListBase} list - Owning list or another PtrBase to copy.
195
+ * @param {object} [node] - Target node.
196
+ * @param {Function} [ListClass] - Expected list constructor for validation.
197
+ */
116
198
  constructor(list, node, ListClass) {
117
199
  if (list instanceof PtrBase) {
118
200
  this.list = list.list;
@@ -132,30 +214,49 @@ export class PtrBase {
132
214
  if (!this.node) this.node = this.list.front;
133
215
  }
134
216
 
217
+ /** The node after the current node. */
135
218
  get nextNode() {
136
219
  return this.node[this.list.nextName];
137
220
  }
138
221
 
222
+ /** The node before the current node. */
139
223
  get prevNode() {
140
224
  return this.node[this.list.prevName];
141
225
  }
142
226
 
227
+ /**
228
+ * Check whether the prevNode link is valid. Always `true` for DLL pointers.
229
+ * @returns {boolean} `true`.
230
+ */
143
231
  isPrevNodeValid() {
144
232
  return true;
145
233
  }
146
234
 
235
+ /**
236
+ * Advance to the next node.
237
+ * @returns {PtrBase} `this` for chaining.
238
+ */
147
239
  next() {
148
240
  this.node = this.node[this.list.nextName];
149
241
  return this;
150
242
  }
151
243
 
244
+ /**
245
+ * Move to the previous node.
246
+ * @returns {PtrBase} `this` for chaining.
247
+ */
152
248
  prev() {
153
249
  this.node = this.node[this.list.prevName];
154
250
  return this;
155
251
  }
156
252
  }
157
253
 
254
+ /** Base class for external (headless) doubly linked lists. */
158
255
  export class ExtListBase {
256
+ /**
257
+ * @param {object|ExtListBase|PtrBase|null} [head=null] - Initial head node, ExtListBase, or PtrBase.
258
+ * @param {object} [options] - Link property names.
259
+ */
159
260
  constructor(head = null, {nextName = 'next', prevName = 'prev'} = {}) {
160
261
  if (head instanceof ExtListBase) {
161
262
  this.nextName = head.nextName;
@@ -174,10 +275,20 @@ export class ExtListBase {
174
275
  this.attach(head);
175
276
  }
176
277
 
278
+ /**
279
+ * Check whether another list is compatible.
280
+ * @param {object} list - List to compare.
281
+ * @returns {boolean} `true` if compatible.
282
+ */
177
283
  isCompatible(list) {
178
284
  return list === this || (list instanceof ExtListBase && this.nextName === list.nextName && this.prevName === list.prevName);
179
285
  }
180
286
 
287
+ /**
288
+ * Check whether a pointer belongs to a compatible list.
289
+ * @param {PtrBase} ptr - Pointer to check.
290
+ * @returns {boolean} `true` if compatible.
291
+ */
181
292
  isCompatiblePtr(ptr) {
182
293
  return (
183
294
  ptr instanceof PtrBase &&
@@ -185,30 +296,40 @@ export class ExtListBase {
185
296
  );
186
297
  }
187
298
 
299
+ /** Whether the list has no nodes. */
188
300
  get isEmpty() {
189
301
  return !this.head;
190
302
  }
191
303
 
304
+ /** Whether the list has exactly one node. */
192
305
  get isOne() {
193
306
  return this.head && this.head[this.nextName] === this.head;
194
307
  }
195
308
 
309
+ /** Whether the list has zero or one node. */
196
310
  get isOneOrEmpty() {
197
311
  return !this.head || this.head[this.nextName] === this.head;
198
312
  }
199
313
 
314
+ /** The head node, or `null` if empty. */
200
315
  get front() {
201
316
  return this.head;
202
317
  }
203
318
 
319
+ /** The last node, or `undefined` if empty. */
204
320
  get back() {
205
321
  return this.head?.[this.prevName];
206
322
  }
207
323
 
324
+ /** A range spanning all nodes, or `null` if empty. */
208
325
  get range() {
209
326
  return this.head ? {from: this.head, to: this.head[this.prevName], list: this.head} : null;
210
327
  }
211
328
 
329
+ /**
330
+ * Count the number of nodes.
331
+ * @returns {number} The node count.
332
+ */
212
333
  getLength() {
213
334
  if (!this.head) return 0;
214
335
 
@@ -222,6 +343,11 @@ export class ExtListBase {
222
343
  return n;
223
344
  }
224
345
 
346
+ /**
347
+ * Set a new head node.
348
+ * @param {object|PtrBase|null} [head=null] - New head node, pointer, or `null`.
349
+ * @returns {object|null} The previous head node.
350
+ */
225
351
  attach(head = null) {
226
352
  const oldHead = this.head;
227
353
  if (head instanceof PtrBase) {
@@ -234,17 +360,29 @@ export class ExtListBase {
234
360
  return oldHead;
235
361
  }
236
362
 
363
+ /**
364
+ * Remove the head reference without modifying nodes.
365
+ * @returns {object|null} The previous head node.
366
+ */
237
367
  detach() {
238
368
  const oldHead = this.head;
239
369
  this.head = null;
240
370
  return oldHead;
241
371
  }
242
372
 
373
+ /**
374
+ * Advance the head to the next node.
375
+ * @returns {ExtListBase} `this` for chaining.
376
+ */
243
377
  next() {
244
378
  if (this.head) this.head = this.head[this.nextName];
245
379
  return this;
246
380
  }
247
381
 
382
+ /**
383
+ * Move the head to the previous node.
384
+ * @returns {ExtListBase} `this` for chaining.
385
+ */
248
386
  prev() {
249
387
  if (this.head) this.head = this.head[this.prevName];
250
388
  return this;