solarite 0.5.2 → 0.7.1

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 (49) hide show
  1. package/LICENSE +21 -0
  2. package/dist/Solarite-debug.js +4847 -3878
  3. package/dist/Solarite.js +4583 -3626
  4. package/dist/Solarite.min.js +2 -4
  5. package/package.json +19 -6
  6. package/readme.md +58 -11
  7. package/src/Globals.js +54 -72
  8. package/src/HtmlParser.js +90 -90
  9. package/src/MultiValueMap.js +57 -105
  10. package/src/NodeGroup.js +624 -470
  11. package/src/Path.js +224 -211
  12. package/src/PathToAttribValue.js +401 -261
  13. package/src/PathToAttribs.js +113 -80
  14. package/src/PathToComment.js +7 -7
  15. package/src/PathToComponent.js +183 -188
  16. package/src/PathToEvent.js +76 -64
  17. package/src/PathToKey.js +19 -0
  18. package/src/PathToNodes.js +1053 -566
  19. package/src/RootNodeGroup.js +120 -8
  20. package/src/Shell.js +570 -348
  21. package/src/Solarite.d.ts +134 -113
  22. package/src/Solarite.js +243 -286
  23. package/src/Template.js +195 -274
  24. package/src/Util.js +353 -351
  25. package/src/assert.js +10 -10
  26. package/src/assignAttributes.js +63 -0
  27. package/src/delve.js +55 -43
  28. package/src/h.js +220 -138
  29. package/src/jsx-dev-runtime.d.ts +1 -0
  30. package/src/jsx-dev-runtime.js +5 -0
  31. package/src/jsx-runtime.d.ts +21 -0
  32. package/src/jsx-runtime.js +84 -0
  33. package/src/jsx.js +194 -0
  34. package/src/toEl.js +77 -82
  35. package/dist/udomdiff-license.txt +0 -18
  36. package/src/getArg.js +0 -137
  37. package/src/hash.js +0 -89
  38. package/src/udomdiff.js +0 -176
  39. package/src/unused/FastLookupArray.js +0 -54
  40. package/src/unused/Hashes.js +0 -339
  41. package/src/unused/InUse.test.js +0 -92
  42. package/src/unused/InUseMap.js +0 -98
  43. package/src/unused/LinkedList.js +0 -117
  44. package/src/unused/LinkedList.test.js +0 -115
  45. package/src/unused/Misc.js +0 -13
  46. package/src/unused/Perf.js +0 -47
  47. package/src/unused/TrackedArray.js +0 -54
  48. package/src/unused/WeakArray.js +0 -33
  49. package/src/watch.js +0 -543
package/src/udomdiff.js DELETED
@@ -1,176 +0,0 @@
1
- /**
2
- * ISC License
3
- *
4
- * Copyright (c) 2020, Andrea Giammarchi, @WebReflection
5
- *
6
- * Permission to use, copy, modify, and/or distribute this software for any
7
- * purpose with or without fee is hereby granted, provided that the above
8
- * copyright notice and this permission notice appear in all copies.
9
- *
10
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
11
- * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12
- * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
13
- * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14
- * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15
- * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16
- * PERFORMANCE OF THIS SOFTWARE.
17
- */
18
-
19
- /**
20
- * @param {Node} parentNode The container where children live
21
- * @param {Node[]} a The list of current/live children
22
- * @param {Node[]} b The list of future children
23
- * @param {(entry: Node, action: number) => Node} get
24
- * The callback invoked per each entry related DOM operation.
25
- * @param {Node} [before] The optional node used as anchor to insert before.
26
- * @returns {Node[]} The same list of future children.
27
- */
28
- const udomdiff = (parentNode, a, b, before) => {
29
- const bLength = b.length;
30
- let aEnd = a.length;
31
- let bEnd = bLength;
32
- let aStart = 0;
33
- let bStart = 0;
34
- let map = null;
35
- while (aStart < aEnd || bStart < bEnd) {
36
- // append head, tail, or nodes in between: fast path
37
- if (aEnd === aStart) {
38
- // we could be in a situation where the rest of nodes that
39
- // need to be added are not at the end, and in such case
40
- // the node to `insertBefore`, if the index is more than 0
41
- // must be retrieved, otherwise it's gonna be the first item.
42
- const node = bEnd < bLength
43
- ? (bStart
44
- ? (b[bStart - 1].nextSibling)
45
- : b[bEnd - bStart])
46
- : before;
47
- while (bStart < bEnd) {
48
- let bNode = b[bStart++];
49
- parentNode.insertBefore(bNode, node);
50
- }
51
- }
52
- // remove head or tail: fast path
53
- else if (bEnd === bStart) {
54
- while (aStart < aEnd) {
55
- // remove the node only if it's unknown or not live
56
- let aNode = a[aStart];
57
- if (!map || !map.has(aNode)) {
58
- parentNode.removeChild(aNode);
59
- }
60
- aStart++;
61
- }
62
- }
63
- // same node: fast path
64
- else if (a[aStart] === b[bStart]) {
65
- aStart++;
66
- bStart++;
67
- }
68
- // same tail: fast path
69
- else if (a[aEnd - 1] === b[bEnd - 1]) {
70
- aEnd--;
71
- bEnd--;
72
- }
73
- // The once here single last swap "fast path" has been removed in v1.1.0
74
- // https://github.com/WebReflection/udomdiff/blob/single-final-swap/esm/index.js#L69-L85
75
- // reverse swap: also fast path
76
- else if (
77
- a[aStart] === b[bEnd - 1] &&
78
- b[bStart] === a[aEnd - 1]
79
- ) {
80
- // this is a "shrink" operation that could happen in these cases:
81
- // [1, 2, 3, 4, 5]
82
- // [1, 4, 3, 2, 5]
83
- // or asymmetric too
84
- // [1, 2, 3, 4, 5]
85
- // [1, 2, 3, 5, 6, 4]
86
- const node = a[--aEnd].nextSibling;
87
-
88
-
89
- let a2 = b[bStart++];
90
- let b2 = a[aStart++];
91
- parentNode.insertBefore(
92
- a2,
93
- b2.nextSibling
94
- );
95
-
96
- let bNode = b[--bEnd];
97
- parentNode.insertBefore(bNode, node);
98
-
99
- // mark the future index as identical (yeah, it's dirty, but cheap 👍)
100
- // The main reason to do this, is that when a[aEnd] will be reached,
101
- // the loop will likely be on the fast path, as identical to b[bEnd].
102
- // In the best case scenario, the next loop will skip the tail,
103
- // but in the worst one, this node will be considered as already
104
- // processed, bailing out pretty quickly from the map index check
105
- a[aEnd] = b[bEnd];
106
- }
107
- // map based fallback, "slow" path
108
- else {
109
- // the map requires an O(bEnd - bStart) operation once
110
- // to store all future nodes indexes for later purposes.
111
- // In the worst case scenario, this is a full O(N) cost,
112
- // and such scenario happens at least when all nodes are different,
113
- // but also if both first and last items of the lists are different
114
- if (!map) {
115
- map = new Map;
116
- let i = bStart;
117
- while (i < bEnd)
118
- map.set(b[i], i++);
119
- }
120
- // if it's a future node, hence it needs some handling
121
- if (map.has(a[aStart])) {
122
- // grab the index of such node, 'cause it might have been processed
123
- const index = map.get(a[aStart]);
124
- // if it's not already processed, look on demand for the next LCS
125
- if (bStart < index && index < bEnd) {
126
- let i = aStart;
127
- // counts the amount of nodes that are the same in the future
128
- let sequence = 1;
129
- while (++i < aEnd && i < bEnd && map.get(a[i]) === (index + sequence))
130
- sequence++;
131
- // effort decision here: if the sequence is longer than replaces
132
- // needed to reach such sequence, which would brings again this loop
133
- // to the fast path, prepend the difference before a sequence,
134
- // and move only the future list index forward, so that aStart
135
- // and bStart will be aligned again, hence on the fast path.
136
- // An example considering aStart and bStart are both 0:
137
- // a: [1, 2, 3, 4]
138
- // b: [7, 1, 2, 3, 6]
139
- // this would place 7 before 1 and, from that time on, 1, 2, and 3
140
- // will be processed at zero cost
141
- if (sequence > (index - bStart)) {
142
- const node = a[aStart];
143
- while (bStart < index) {
144
- let bNode = b[bStart++];
145
- parentNode.insertBefore(bNode, node);
146
- }
147
- }
148
- // if the effort wasn't good enough, fallback to a replace,
149
- // moving both source and target indexes forward, hoping that some
150
- // similar node will be found later on, to go back to the fast path
151
- else {
152
- let aNode = a[aStart++]
153
- let bNode = b[bStart++]
154
- parentNode.replaceChild(
155
- bNode,
156
- aNode
157
- );
158
- }
159
- }
160
- // otherwise move the source forward, 'cause there's nothing to do
161
- else
162
- aStart++;
163
- }
164
- // this node has no meaning in the future list, so it's more than safe
165
- // to remove it, and check the next live node out instead, meaning
166
- // that only the live list index should be forwarded
167
- else {
168
- let aNode = a[aStart++];
169
- parentNode.removeChild(aNode);
170
- }
171
- }
172
- }
173
- return b;
174
- };
175
-
176
- export default udomdiff;
@@ -1,54 +0,0 @@
1
- /**
2
- * partialUpdate test is 20% slower when using this, even before I override any methods!*/
3
- export default class FastLookupArray extends Array {
4
- constructor() {
5
- super(...arguments)
6
- this.indexMap = new Map(); // You can replace with WeakMap() but ensure only objects are added.
7
-
8
- }
9
-
10
- push(item) { // doesn't support pushing multiple
11
- if (!this.indexMap.has(item)) {
12
- this[this.length] = item;
13
- this.indexMap.set(item, this.length - 1);
14
- }
15
- }
16
-
17
- indexOf(item) {
18
- return this.indexMap.get(item) || -1;
19
- }
20
-
21
- remove(item) {
22
- const index = this.indexOf(item);
23
- if (index !== -1) {
24
- this.splice(index, 1);
25
- this.indexMap.delete(item);
26
-
27
- // Adjust the map indices for the items after the removed one
28
- for (let i = index; i < this.length; i++)
29
- this.indexMap.set(this[i], i);
30
- }
31
- }
32
-
33
- insertBefore(referenceItem, newItem) {
34
- const refIndex = this.indexOf(referenceItem);
35
- if (refIndex !== -1) {
36
- this.splice(refIndex, 0, newItem);
37
- this.indexMap.set(newItem, refIndex);
38
-
39
- // Adjust the map indices for the items after the inserted one
40
- for (let i = refIndex + 1; i < this.length; i++)
41
- this.indexMap.set(this[i], i);
42
- }
43
- }
44
-
45
- set(index, item) {
46
- const currentItem = this[index];
47
- if (currentItem !== undefined)
48
- this.indexMap.delete(currentItem);
49
- this[index] = item;
50
- this.indexMap.set(item, index);
51
- }
52
-
53
- // TODO: Override splice?
54
- }
@@ -1,339 +0,0 @@
1
- import {getObjectId} from "../hash.js";
2
- import Template from "../Template.js";
3
-
4
- /**
5
- * Convert obj to a non-cyclic form that can be given to JSON.serialize.
6
- * This is useful for creating a string that represents a hash of all the deep values of an object.
7
- *
8
- * One instance of a node always has the same hash, even if its attributes/children have changed.
9
- *
10
- * TODO: Could memoize be faster if given an old version of the same object, and it only finds the differences?
11
- * Or if we inline getObjectId()
12
- *
13
- * @param obj {Object|Array|function|Node}
14
- * @param seenMap Used internally.
15
- * @param idCounter Used internally.
16
- * @returns {{}|*|string} */
17
- export function memoize(obj, seenMap = new Map(), idCounter = {value: 0}) {
18
-
19
- // If obj is a Node, Element, or Window, we treat it specially
20
- if (obj?.nodeType) { // Benchmarking shows this is faster than "instanceof Node"
21
- let nodeId = getObjectId(obj);
22
- return `&N:${nodeId}`;
23
- }
24
-
25
- // TODO: Should I instead use id's to keep track of functions?
26
- let type = typeof obj
27
-
28
- if (obj && type === 'object') {
29
- if (seenMap.has(obj))
30
- return `&O:${seenMap.get(obj)}`;
31
-
32
- else {
33
- seenMap.set(obj, idCounter.value++);
34
- if (typeof obj.memoize === 'function')
35
- return obj.memoize();
36
-
37
- // We iterate through the keys of an object because an object may have changed since the last time we saw it.
38
- const serializedObj = {};
39
- for (let key in obj)
40
- serializedObj[key] = memoize(obj[key], seenMap, idCounter);
41
- return serializedObj;
42
- }
43
- } else if (type === 'function')
44
- //return `&F:${obj}` // String version of function. This version fails the loop.eventBindings test.
45
- return `&F:${getObjectId(obj)}`; // Memory reference to function. this makes it twice as slow!
46
-
47
- else
48
- return obj;
49
- }
50
-
51
-
52
- function fnv1a(...data) {
53
- let hash = 0x811c9dc5; // FNV offset basis
54
- for (let i = 0; i < data.length; i++) {
55
- hash ^= data[i]; // XOR
56
- hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24); // FNV prime multiplication
57
- }
58
- return hash >>> 0; // Convert to 32-bit unsigned integer
59
- }
60
-
61
- const FNV_PRIME_64 = BigInt("1099511628211");
62
- const OFFSET_BASIS_64 = BigInt("14695981039346656037");
63
- function fnv1a_64bit(...data) {
64
- let hash = OFFSET_BASIS_64;
65
- for (let i = 0; i < data.length; i++) {
66
- hash ^= data[i]; // XOR
67
- // hash = BigInt.asUintN(64, hash*FNV_PRIME_64);
68
- }
69
- return hash;
70
- }
71
-
72
-
73
- // Faster than memoize
74
- export function hashObject(obj) {
75
- let combinedData = (0);
76
- if (obj === null)
77
- return combinedData;
78
-
79
- if (Array.isArray(obj)) {
80
- for (let i=(0); i<obj.length; i++) {
81
- let v = hashObject(obj[i])
82
- combinedData = fnv1a(combinedData, i, v);
83
- }
84
- }
85
-
86
- else if (typeof obj === 'object') {
87
- let i = (0);
88
- for (const key in obj) {
89
- let k = getObjectId3(key)
90
- let v = hashObject(obj[key])
91
- combinedData = fnv1a(combinedData, i, k, v);
92
- i++
93
- }
94
- }
95
- else if (typeof obj === 'number')
96
- return (obj)
97
- else if (typeof obj === 'string')
98
- return getObjectId3(obj)
99
- else
100
- return getObjectId2(obj);
101
-
102
- return combinedData;
103
- }
104
-
105
- // TODO: Use this number instead as the high bits for getObjectId2?
106
- let lastObjectId2 = (1_010_101_101); // Big enough to not easily not collide with the space of unhashed numbers.
107
- let objectIds2 = new Map();
108
-
109
- export function getObjectId2(obj) {
110
- let result = objectIds2.get(obj);
111
- if (!result) {
112
- result = (lastObjectId2++); // convert to string, store in result, then add 1 to lastObjectId.
113
- objectIds2.set(obj, result)
114
- }
115
- return result;
116
- }
117
-
118
-
119
- let objectIds3 = {};
120
-
121
- export function getObjectId3(obj) {
122
- // if (typeof obj === 'string') {
123
- // let l = obj.length;
124
- // if (l < 512) { // Faster than getObjectId3. 512 was picked randomly and has not been benchmarked.
125
- // let result = 1;
126
- // for (let i=0; i < l; i++)
127
- // result ^= obj.charCodeAt(i) << (i%16);
128
- // return result
129
- // }
130
- // }
131
-
132
-
133
- let result = objectIds3[obj];
134
- if (!result) {
135
- result = (lastObjectId2++); // convert to string, store in result, then add 1 to lastObjectId.
136
- objectIds3[obj] = result
137
- }
138
- return result;
139
- }
140
-
141
-
142
- let hash64Cache = new WeakMap();
143
- export {hash64Cache};
144
-
145
- // 25% slower than 32-bit version but still faster than memoize+JSON.stringify()
146
- // TODO: hardcoded hash values for true and false?
147
- export function hashObject64(obj) {
148
- let resultLow = 0;
149
- let resultHigh = 0;
150
-
151
- if (obj instanceof Template)
152
- obj = [obj.htmlId, ...obj.exprs]
153
-
154
- if (obj === null)
155
- return [0, 0];
156
-
157
- else if (Array.isArray(obj)) {
158
- let result
159
- // = hash64Cache.get(obj);
160
- // if (!result) {
161
- for (let i = (0); i < obj.length; i++) {
162
- let [vLow, vHigh] = hashObject64(obj[i])
163
- resultLow = fnv1a(resultLow, i, vLow)
164
- resultHigh = fnv1a(resultHigh, vHigh)
165
- }
166
- result = [resultLow, resultHigh]
167
- // hash64Cache.set(obj, result)
168
- //}
169
- return result;
170
- }
171
-
172
- else if (typeof obj === 'object') {
173
- let result
174
- // = hash64Cache.get(obj);
175
- // if (!result) {
176
- let i = (0);
177
- for (const key in obj) {
178
- let k = getObjectId3(key)
179
- let [vLow, vHigh] = hashObject64(obj[key])
180
- resultLow = fnv1a(resultLow, i, vLow)
181
- resultHigh = fnv1a(resultHigh, k, vHigh)
182
- i++
183
- }
184
- result = [resultLow, resultHigh]
185
- // hash64Cache.set(obj, result)
186
- //}
187
-
188
- return result;
189
- }
190
- else if (typeof obj === 'number')
191
- return [0, obj]
192
- else if (typeof obj === 'string')
193
- return [0, getObjectId3(obj)]
194
- else
195
- return [0, getObjectId2(obj)];
196
- }
197
-
198
-
199
-
200
-
201
- // Perforamnce varies greatly.
202
- export function memoize2(obj) {
203
-
204
- if (obj === null)
205
- return 'null';
206
-
207
- switch (obj?.constructor) {
208
- case Function:
209
- case Node:
210
- return getObjectId(obj);
211
- case Array:
212
- return '[' + obj.map(item => memoize2(item)) + ']'
213
- case Object:
214
- let result = '{';
215
- for (let key in obj) {
216
- //key = key.match(/[^A-Z0-9_]/i) ? JSON.stringify(key) : key;
217
- key = (key.includes(':')) ? JSON.stringify(key) : key;
218
- result += `${key}:${memoize2(obj[key])}`
219
- }
220
- return result +'}';
221
- default:
222
- return JSON.stringify(obj);
223
- }
224
- }
225
-
226
- // as fast as memoize2, or faster.
227
- export function memoize3(obj) {
228
-
229
- if (obj === null)
230
- return 'null';
231
-
232
- let type = typeof obj;
233
- if (Array.isArray(obj))
234
- return '[' + obj.map(item => memoize2(item)) + ']'
235
- if (obj instanceof Node || type === 'function')
236
- return getObjectId(obj);
237
- if (type=== 'object') {
238
- let result = '{';
239
- for (let key in obj) {
240
- //key = key.match(/[^A-Z0-9_]/i) ? JSON.stringify(key) : key;
241
- key = (key.includes(':')) ? JSON.stringify(key) : key;
242
- result += `${key}:${memoize2(obj[key])}`
243
- }
244
- return result +'}';
245
- }
246
- return JSON.stringify(obj);
247
- }
248
-
249
-
250
-
251
-
252
- // as fast as memoize2, or faster.
253
- export function memoize4(obj, seenMap=new Map(), idCounter={value: 0}) {
254
- let result;
255
- if (obj instanceof Template) {
256
- if (obj.exprs.length === 1)
257
- return obj.htmlId + '\f' + memoize4(obj.exprs[0]) // \f is the "Form feed" control character, unlikely to be usedin regular text.
258
-
259
- let exprLength = obj.exprs.length;
260
- result = new Array(exprLength + 1);
261
- result[0] = obj.htmlId;
262
- let exprs = obj.exprs;
263
- for (let i = 0; i < exprLength; i++)
264
- result[i + 1] = memoize4(exprs[i])
265
- }
266
-
267
- else if (obj === null)
268
- result = 'null';
269
-
270
- else if (Array.isArray(obj)) {
271
- if (seenMap.has(obj))
272
- result = `&A${seenMap.get(obj)}`;
273
- else {
274
- seenMap.set(obj, idCounter.value++);
275
- result = '[' + obj.map(item => memoize2(item)) + ']'
276
- }
277
- }
278
- else if (obj instanceof Node || typeof obj === 'function')
279
- result = getObjectId(obj);
280
-
281
- else if (typeof obj=== 'object') {
282
- if (seenMap.has(obj))
283
- result = `&O${seenMap.get(obj)}`;
284
-
285
- else {
286
- seenMap.set(obj, idCounter.value++);
287
-
288
- // // String contact approach.
289
- // result = '{';
290
- // for (let key in obj) {
291
- // //key = key.match(/[^A-Z0-9_]/i) ? JSON.stringify(key) : key;
292
- // key = (key.includes(':')) ? JSON.stringify(key) : key;
293
- // result += `${key}:${memoize2(obj[key])}`
294
- // }
295
- // result = result + '}';
296
-
297
- // Buffer approach. Seems slightly faster.
298
- let keys = Object.keys(obj);
299
- let buffer = new Array(keys.length) + 2;
300
- buffer[0] = '{'
301
- buffer[buffer.length-1] = '}'
302
- let idx = 1;
303
- for (let key of keys) {
304
- //key = key.match(/[^A-Z0-9_]/i) ? JSON.stringify(key) : key;
305
- key = (key.includes(':')) ? JSON.stringify(key) : key;
306
- buffer[idx] = `${key}:${memoize2(obj[key])},`
307
- idx++;
308
- }
309
- result = buffer.join('');
310
- }
311
- }
312
- else
313
- result = JSON.stringify(obj);
314
-
315
-
316
- return result;
317
- }
318
-
319
-
320
-
321
-
322
-
323
- // Takes half as long as just calling JSON.serialize!
324
- function containsFunction(obj) {
325
- // Base case: if the object itself is a function
326
- let type = typeof obj;
327
- if (type === 'function') {
328
- return true;
329
- }
330
-
331
- // If the object is an object or array, recursively search its properties
332
- if (type === 'object' && obj !== null)
333
- for (let key in obj)
334
- if (containsFunction(obj[key]))
335
- return true;
336
-
337
- // If none of the properties are functions, return false
338
- return false;
339
- }
@@ -1,92 +0,0 @@
1
- import {InUseArray, InUseMap} from "./InUseMap.js";
2
- import Testimony, {assert} from "../../tests/Testimony.js";
3
-
4
- Testimony.test('InUseArray.constructor', () => {
5
- const arr = new InUseArray();
6
- assert.eq(arr.count, 0, 'Initial count should be 0');
7
- assert.eq(arr.length, 0, 'Initial length should be 0');
8
- });
9
-
10
- Testimony.test('InUseArray.use - with no value', () => {
11
- const arr = new InUseArray(1, 2, 3);
12
- const val = arr.use();
13
- assert.eq(val, 1, 'Should return the first value');
14
- assert.eq(arr.count, 1, 'Count should be incremented');
15
- });
16
-
17
- Testimony.test('InUseArray.use - with specific value', () => {
18
- const arr = new InUseArray(1, 2, 3);
19
- arr.count = 1; // Mark the first element as in-use
20
- const val = arr.use(3);
21
- assert.eq(val, 3, 'Should return the specified value');
22
- assert.eq(arr.count, 2, 'Count should be incremented');
23
- assert.eq(arr[1], 3, 'Value should be moved to the in-use section');
24
- assert.eq(arr[2], 2, 'Remaining value should be in the available section');
25
- });
26
-
27
- Testimony.test('InUseArray.use', () => {
28
- const arr = new InUseArray(1, 2, 3);
29
- let val = arr.use(4);
30
- assert.eq(val, undefined,'Should return undefined');
31
- assert.eq(arr.use(), 1);
32
- assert.eq(arr.use(3), 3);
33
- assert.eq(arr.use(), 2);
34
- assert.eq(arr.use(), undefined);
35
- });
36
-
37
- Testimony.test('InUseArray.use - all in use', () => {
38
- const arr = new InUseArray(1, 2, 3);
39
- arr.count = 3;
40
- const val = arr.use();
41
- assert.eq(val, undefined, 'Should return undefined');
42
- });
43
-
44
- Testimony.test('InUseArray.free', () => {
45
- const arr = new InUseArray(1, 2, 3);
46
- arr.count = 3;
47
- arr.free();
48
- assert.eq(arr.count, 0, 'Count should be reset to 0');
49
- });
50
-
51
- Testimony.test('InUseArray.reset', () => {
52
- const arr = new InUseArray(1, 2, 3);
53
- arr.reset();
54
- assert.eq(arr.length, 0, 'Array should be empty');
55
- });
56
-
57
-
58
-
59
-
60
- Testimony.test('InUseMap.add', () => {
61
- const map = new InUseMap();
62
- map.add('key', 'value');
63
- assert.eq(map.data['key'][0], 'value', 'Value should be added to the map');
64
- });
65
-
66
- Testimony.test('InUseMap.getAll', () => {
67
- const map = new InUseMap();
68
- map.add('key', 'value');
69
- const values = map.getAll('key');
70
- assert.eq(values.length, 1, 'Should return an array with one value');
71
- assert.eq(values[0], 'value', 'Should return the correct value');
72
- });
73
-
74
- Testimony.test('InUseMap.use', () => {
75
- const map = new InUseMap();
76
- map.add('key', 'value');
77
- let value = map.use('key');
78
- assert.eq(value, 'value', 'Should return and mark the value as in-use');
79
- value = map.use('key');
80
- assert.eq(value, undefined, 'Should return and mark the value as in-use');
81
- });
82
-
83
- Testimony.test('InUseMap.hasValue', () => {
84
- const map = new InUseMap();
85
- map.add('key1', 'value1');
86
- map.add('key2', 'value2');
87
- const keys = map.hasValue('value1');
88
- assert.eq(keys.length, 1, 'Should return an array with one key');
89
- assert.eq(keys[0], 'key1', 'Should return the correct key');
90
- });
91
-
92
-