@creejs/commons-lang 2.1.11 → 2.1.13

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.
@@ -14,7 +14,7 @@
14
14
  defaults,
15
15
  extend,
16
16
  extends: extend,
17
- equals: equals$1,
17
+ equals: equals$2,
18
18
  isBrowser,
19
19
  isNode
20
20
  };
@@ -82,7 +82,7 @@
82
82
  * @param {*} value2 - Second value to compare
83
83
  * @returns {boolean} True if values are equal, false otherwise
84
84
  */
85
- function equals$1 (value1, value2) {
85
+ function equals$2 (value1, value2) {
86
86
  if (value1 === value2) {
87
87
  return true
88
88
  }
@@ -581,7 +581,7 @@
581
581
  */
582
582
  function assertArray (value, paramName) {
583
583
  if (!Array.isArray(value)) {
584
- throw new Error(`${paramName ? paramName + '' : ' '}Not Array: type=${typeof value} value=${JSON.stringify(value)}`)
584
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Array: type=${typeof value} value=${JSON.stringify(value)}`)
585
585
  }
586
586
  }
587
587
  /**
@@ -1405,7 +1405,20 @@
1405
1405
  quietKeepError
1406
1406
  };
1407
1407
 
1408
- // @ts-nocheck
1408
+ // owned
1409
+
1410
+ /**
1411
+ * @typedef {{
1412
+ * promise: Promise<*>,
1413
+ * timerHandler: NodeJS.Timeout,
1414
+ * timerCleared: boolean,
1415
+ * resolved: boolean,
1416
+ * rejected: boolean,
1417
+ * canceled: boolean,
1418
+ * reject: (reason: Error)=> void,
1419
+ * resolve: (...args:any[])=> void
1420
+ * }} Deferred
1421
+ */
1409
1422
 
1410
1423
  /**
1411
1424
  * @module PromiseUtils
@@ -1428,12 +1441,16 @@
1428
1441
  * 1. timeout=-1, it means no timeout check
1429
1442
  * @param {number} [timeout=-1] - Timeout duration in milliseconds
1430
1443
  * @param {string} [timeoutMessage]
1431
- * @returns {{promise: Promise<*>, reject: function, resolve: function}}
1444
+ * @returns {Deferred}
1432
1445
  */
1433
1446
  function defer (timeout = -1, timeoutMessage) {
1434
1447
  assertNumber(timeout);
1448
+ /** @type {Deferred} */
1435
1449
  const rtnVal = {};
1436
1450
 
1451
+ /**
1452
+ * @type {NodeJS.Timeout}
1453
+ */
1437
1454
  let timerHandler;
1438
1455
  if (timeout >= 0) {
1439
1456
  rtnVal.timerHandler = timerHandler = setTimeout(() => {
@@ -1441,17 +1458,16 @@
1441
1458
  rtnVal.timerCleared = true; // easy to check in test case
1442
1459
  rtnVal.reject(new Error(timeoutMessage ?? `Promise Timeout: ${timeout}ms`));
1443
1460
  }, timeout);
1444
- rtnVal.timerHandler = timerHandler;
1445
1461
  }
1446
1462
 
1447
1463
  rtnVal.promise = new Promise((resolve, reject) => {
1448
- rtnVal.resolve = (...args) => {
1464
+ rtnVal.resolve = (arg) => {
1449
1465
  if (timerHandler != null) {
1450
1466
  clearTimeout(timerHandler); // must clear it
1451
1467
  rtnVal.timerCleared = true; // easy to check in test case
1452
1468
  }
1453
1469
  rtnVal.resolved = true;
1454
- resolve(...args);
1470
+ resolve(arg);
1455
1471
  };
1456
1472
 
1457
1473
  rtnVal.reject = (err) => {
@@ -1463,12 +1479,14 @@
1463
1479
  reject(err);
1464
1480
  };
1465
1481
  });
1482
+ // @ts-ignore
1466
1483
  rtnVal.promise.cancel = () => {
1467
1484
  if (timerHandler != null) {
1468
1485
  clearTimeout(timerHandler); // must clear it
1469
1486
  rtnVal.timerCleared = true; // easy to check in test case
1470
1487
  }
1471
1488
  rtnVal.rejected = true; // easy to check in test case
1489
+ // @ts-ignore
1472
1490
  rtnVal.canceled = rtnVal.promise.canceled = true; // easy to check in test case
1473
1491
  rtnVal.reject(new Error('Cancelled'));
1474
1492
  };
@@ -1515,8 +1533,8 @@
1515
1533
  * 2. It's NOT convenient to use Promise.allSettled() to get the results of all promises.
1516
1534
  * * the data structure is not consistent when fullfilled or rejected
1517
1535
  * * have to check "string" type of status to know sucess or failure
1518
- * @param {Promise} promises
1519
- * @returns {Array<{ok: boolean, result: any}>}
1536
+ * @param {Promise<*>[]} promises
1537
+ * @returns {Promise<{ok: boolean, result: any}[]>}
1520
1538
  */
1521
1539
  async function allSettled (promises) {
1522
1540
  assertArray(promises);
@@ -1559,13 +1577,14 @@
1559
1577
  *
1560
1578
  * @param {Promise<*>|number|undefined} [promise] - The input promise to delay
1561
1579
  * @param {number|undefined} [ms] - Minimum delay in milliseconds (default: 1)
1562
- * @returns {Promise} A new promise that settles after the delay period
1580
+ * @returns {Promise<*>} A new promise that settles after the delay period
1563
1581
  */
1564
1582
  function delay (promise, ms) {
1565
- if (isNumber(promise)) {
1583
+ if (isNumber(promise)) { // defer(ms)
1584
+ // @ts-ignore
1566
1585
  ms = promise;
1567
1586
  promise = Promise.resolve();
1568
- } else if (promise == null && ms == null) {
1587
+ } else if (promise == null && ms == null) { // defer(promise, ms)
1569
1588
  ms = 1;
1570
1589
  promise = Promise.resolve();
1571
1590
  }
@@ -1574,16 +1593,16 @@
1574
1593
  assertNumber(ms);
1575
1594
  const deferred = defer();
1576
1595
  const startTs = Date.now();
1577
- promise
1578
- .then((...args) => {
1579
- const escaped = Date.now() - startTs;
1580
- if (escaped < ms) {
1581
- setTimeout(() => deferred.resolve(...args), ms - escaped);
1582
- } else {
1583
- deferred.resolve(...args);
1584
- }
1585
- })
1586
- .catch((err) => {
1596
+ // @ts-ignore
1597
+ promise.then((...args) => {
1598
+ const escaped = Date.now() - startTs;
1599
+ if (escaped < ms) {
1600
+ setTimeout(() => deferred.resolve(...args), ms - escaped);
1601
+ } else {
1602
+ deferred.resolve(...args);
1603
+ }
1604
+ })
1605
+ .catch((/** @type {Error} */ err) => {
1587
1606
  const escaped = Date.now() - startTs;
1588
1607
  if (escaped < ms) {
1589
1608
  setTimeout(() => deferred.reject(err), ms - escaped);
@@ -1599,8 +1618,8 @@
1599
1618
  * 1. export function are executed one by one
1600
1619
  * 2. Fast Fail: if any tasks fail, the whole chain is rejected with the first error
1601
1620
  * 3. if an element is not function, rejects the whole chain with Error(Not Function)
1602
- * @param {Function[]} promises
1603
- * @returns {Promise<Array>} Promise that resolves with an array of results in the same order as input tasks
1621
+ * @param {Function[]} tasks
1622
+ * @returns {Promise<any[]>} Promise that resolves with an array of results in the same order as input tasks
1604
1623
  */
1605
1624
  async function series (tasks) {
1606
1625
  assertArray(tasks);
@@ -1640,7 +1659,7 @@
1640
1659
  * 2. rejects whole chain with the first error, when first task fails
1641
1660
  * @param {Function[]} tasks
1642
1661
  * @param {number} [maxParallel=5]
1643
- * @returns {Promise<Array>} Array of resolved values from all promises
1662
+ * @returns {Promise<any[]>} Array of resolved values from all promises
1644
1663
  * @throws {TypeError} If input is not an array of export function or maxParallel is not a number
1645
1664
  */
1646
1665
  async function parallel (tasks, maxParallel = 5) {
@@ -1682,7 +1701,7 @@
1682
1701
  * 2. all tasks will be executed, even some of them failed.
1683
1702
  * @param {Function[]} tasks
1684
1703
  * @param {number} [maxParallel=5] - Maximum number of tasks to run in parallel
1685
- * @returns {Promise<Array>} Array of resolved values from all promises
1704
+ * @returns {Promise<any[]>} Array of resolved values from all promises
1686
1705
  * @throws {TypeError} If input is not an array of export function or maxParallel is not a number
1687
1706
  */
1688
1707
  async function parallelAllSettled (tasks, maxParallel = 5) {
@@ -1910,7 +1929,7 @@
1910
1929
  var TypedArrayUtils = {
1911
1930
  startsWith,
1912
1931
  isSameType,
1913
- equals
1932
+ equals: equals$1
1914
1933
  };
1915
1934
 
1916
1935
  /**
@@ -1925,7 +1944,7 @@
1925
1944
  assertNotNil(searching, 'searching');
1926
1945
 
1927
1946
  const header = src.subarray(0, searching.length);
1928
- return equals(header, searching)
1947
+ return equals$1(header, searching)
1929
1948
  }
1930
1949
 
1931
1950
  /**
@@ -1951,7 +1970,7 @@
1951
1970
  * @returns {boolean} True if the typed arrays are equal, false otherwise.
1952
1971
  * @throws {Error} If either `src` or `target` is null or undefined.
1953
1972
  */
1954
- function equals (src, target) {
1973
+ function equals$1 (src, target) {
1955
1974
  assertNotNil(src, 'src');
1956
1975
  assertNotNil(target, 'target');
1957
1976
  if (!isSameType(src, target)) {
@@ -2096,21 +2115,164 @@
2096
2115
  targetView.set(dataView, targetOffset);
2097
2116
  }
2098
2117
 
2118
+ // module vars
2119
+ const ms2ns = 1_000_000;
2120
+ const s2ns = 1_000_000_000;
2121
+
2099
2122
  var TimeUtils = {
2100
- timestamp64
2123
+ s2ns,
2124
+ ms2ns,
2125
+ timestamp64,
2126
+ lapseNano,
2127
+ lapseMillis,
2128
+ timeoutNano,
2129
+ timeoutMillis
2101
2130
  };
2102
2131
 
2103
- const ms2ns = BigInt(1_000_000);
2104
2132
  /**
2105
2133
  * Gets the current timestamp in nanoseconds (if running in Node.js) or milliseconds (in browser).
2106
2134
  * Uses `process.hrtime.bigint()` for high-resolution timestamps in Node.js, falls back to `Date.now()` in browsers.
2107
2135
  * @returns {bigint} Current timestamp as a BigInt
2108
2136
  */
2109
2137
  function timestamp64 () {
2110
- if (typeof performance !== 'undefined') {
2111
- return BigInt(Math.floor(performance.timeOrigin + performance.now())) * ms2ns
2138
+ // sinon can not fake performance.timeOrigin, so we have to check it
2139
+ if (typeof performance !== 'undefined' && typeof performance.timeOrigin === 'number') {
2140
+ // timeOrigin specifies the high resolution millisecond timestamp, eg. 1756350801931.159
2141
+ const base = performance.timeOrigin;
2142
+ // the current high resolution millisecond timestamp, eg.31767926.416357
2143
+ const now = performance.now();
2144
+ return BigInt((base + now) * ms2ns)
2112
2145
  }
2113
- return BigInt(Date.now()) * ms2ns
2146
+ return BigInt(Date.now() * ms2ns)
2147
+ }
2148
+
2149
+ /**
2150
+ * Calculates the time elapsed in nanoseconds between the given timestamp and now.
2151
+ * @param {bigint} start - start timestamp64, in nanoseconds.
2152
+ * @param {bigint} [end] - end timestamp64, in nanoseconds. If not provided, uses current timestamp64.
2153
+ * @returns {bigint} The elapsed time in nanoseconds (current timestamp64 - ts64).
2154
+ */
2155
+ function lapseNano (start, end) {
2156
+ return (end ?? timestamp64()) - start
2157
+ }
2158
+
2159
+ /**
2160
+ * Calculates the time elapsed in milliseconds between the given timestamp and now.
2161
+ * @param {bigint} start - start The timestamp in 64-bit format.
2162
+ * @param {bigint} [end] - end timestamp64, in nanoseconds. If not provided, uses current timestamp64.
2163
+ * @returns {bigint} The elapsed time in milliseconds.
2164
+ */
2165
+ function lapseMillis (start, end) {
2166
+ end = end ?? timestamp64();
2167
+ const lapseNano = end - start;
2168
+ return BigInt(lapseNano) / BigInt(ms2ns)
2169
+ }
2170
+
2171
+ /**
2172
+ * compare current timestamp64 against the given ts64, and check if the elapsed time exceeds the specified timeout.
2173
+ * @param {bigint} nanoTimestamp64 - The timestamp to compare against (in nanoseconds).
2174
+ * @param {bigint|number} nanoTimeout - The timeout threshold (in nanoseconds).
2175
+ * @returns {boolean} True if elapsed time exceeds timeout, false otherwise.
2176
+ */
2177
+ function timeoutNano (nanoTimestamp64, nanoTimeout) {
2178
+ return lapseNano(nanoTimestamp64) > nanoTimeout
2179
+ }
2180
+
2181
+ /**
2182
+ * compare current timestamp64 against the given ts64, and check if the elapsed time exceeds the specified timeout.
2183
+ * @param {bigint} nanoTimestamp64 - The timestamp to compare against (in nanoseconds).
2184
+ * @param {bigint|number} millisTimeout - The timeout threshold (in milliseconds).
2185
+ * @returns {boolean} True if elapsed time exceeds timeout, false otherwise.
2186
+ */
2187
+ function timeoutMillis (nanoTimestamp64, millisTimeout) {
2188
+ return lapseMillis(nanoTimestamp64) > millisTimeout
2189
+ }
2190
+
2191
+ // owned
2192
+
2193
+ var ArrayUtils = {
2194
+ first,
2195
+ last,
2196
+ equals,
2197
+ equalsIgnoreOrder
2198
+ };
2199
+
2200
+ /**
2201
+ * Gets the first element of an array
2202
+ * @param {any[]} arr - The input array
2203
+ * @param {any} [defaultValue] - The value to return if the array is empty or first element is undefined/null.
2204
+ * @returns {any} The first element of the array, or the defaultValue if the array is empty or not an array.
2205
+ * @throws {Error} if arr is not an array
2206
+ */
2207
+ function first (arr, defaultValue) {
2208
+ assertArray(arr, 'arr');
2209
+ return arr[0] ?? defaultValue
2210
+ }
2211
+
2212
+ /**
2213
+ * Gets the last element of an array
2214
+ * @param {any[]} arr - The input array
2215
+ * @param {any} [defaultValue] - The value to return if the array is empty or last element is undefined/null
2216
+ * @returns {any} The last element of the array or the defaultValue
2217
+ * @throws {Error} if arr is not an array
2218
+ */
2219
+ function last (arr, defaultValue) {
2220
+ assertArray(arr, 'arr');
2221
+ return arr[arr.length - 1] ?? defaultValue
2222
+ }
2223
+
2224
+ /**
2225
+ * Checks if two arrays are equal ignoring element order
2226
+ * @param {any[]} arr1 - first array to compare
2227
+ * @param {any[]} arr2 - Second array to compare
2228
+ * @param {(a:any, b:any) => 0|1|-1} [compareFn]
2229
+ * @returns {boolean} True if arrays have same elements (order-independent), false otherwise
2230
+ */
2231
+ function equalsIgnoreOrder (arr1, arr2, compareFn) {
2232
+ if (!Array.isArray(arr1) || !Array.isArray(arr2)) {
2233
+ return false
2234
+ }
2235
+ if (arr1.length !== arr2.length) {
2236
+ return false
2237
+ }
2238
+ arr1.sort(compareFn);
2239
+ arr2.sort(compareFn);
2240
+ for (let i = 0; i < arr1.length; i++) {
2241
+ if (compareFn) {
2242
+ if (compareFn(arr1[i], arr2[i]) !== 0) {
2243
+ return false
2244
+ }
2245
+ } else if (arr1[i] !== arr2[i]) {
2246
+ return false
2247
+ }
2248
+ }
2249
+ return true
2250
+ }
2251
+
2252
+ /**
2253
+ * Checks if two arrays are equal by order
2254
+ * @param {any[]} arr1 - first array to compare
2255
+ * @param {any[]} arr2 - Second array to compare
2256
+ * @param {(a:any, b:any) => 0|1|-1} [compareFn]
2257
+ * @returns {boolean} True if arrays have same elements (order-independent), false otherwise
2258
+ */
2259
+ function equals (arr1, arr2, compareFn) {
2260
+ if (!Array.isArray(arr1) || !Array.isArray(arr2)) {
2261
+ return false
2262
+ }
2263
+ if (arr1.length !== arr2.length) {
2264
+ return false
2265
+ }
2266
+ for (let i = 0; i < arr1.length; i++) {
2267
+ if (compareFn) {
2268
+ if (compareFn(arr1[i], arr2[i]) !== 0) {
2269
+ return false
2270
+ }
2271
+ } else if (arr1[i] !== arr2[i]) {
2272
+ return false
2273
+ }
2274
+ }
2275
+ return true
2114
2276
  }
2115
2277
 
2116
2278
  /**
@@ -2134,10 +2296,12 @@
2134
2296
  ReflectUtils,
2135
2297
  TypedArrayUtils,
2136
2298
  ArrayBufferUtils,
2137
- TimeUtils
2299
+ TimeUtils,
2300
+ ArrayUtils
2138
2301
  };
2139
2302
 
2140
2303
  exports.ArrayBufferUtils = ArrayBufferUtils;
2304
+ exports.ArrayUtils = ArrayUtils;
2141
2305
  exports.ClassProxyUtils = ClassProxyUtils;
2142
2306
  exports.Exec = ExecUtils;
2143
2307
  exports.ExecUtils = ExecUtils;