@yorozu/utils 0.5.3 → 1.0.25

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.
@@ -0,0 +1,25 @@
1
+ export type BitmapPri = "visible" | "preload";
2
+ export type BitmapWorkJob = {
3
+ id: string;
4
+ pri: BitmapPri;
5
+ source: Blob | ImageBitmapSource;
6
+ run?: (ctx: {
7
+ signal: AbortSignal;
8
+ bitmap: ImageBitmap;
9
+ }) => Promise<void>;
10
+ };
11
+ export type BitmapWorkQueueStats = {
12
+ active: number;
13
+ queued: number;
14
+ };
15
+ export type BitmapWorkQueue = {
16
+ enqueue(job: BitmapWorkJob): boolean;
17
+ cancel(id: string): boolean;
18
+ pause(): void;
19
+ resume(): void;
20
+ readonly stats: BitmapWorkQueueStats;
21
+ };
22
+ export declare function createBitmapWorkQueue(opts?: {
23
+ concurrency?: number;
24
+ idle?: boolean;
25
+ }): BitmapWorkQueue;
@@ -0,0 +1,10 @@
1
+ export type IdleDeadline = {
2
+ didTimeout: boolean;
3
+ timeRemaining(): number;
4
+ };
5
+ export type IdleHandle = {
6
+ cancel(): void;
7
+ };
8
+ export declare function requestIdle(fn: (deadline: IdleDeadline) => void, opts?: {
9
+ timeout?: number;
10
+ }): IdleHandle;
package/async/index.d.ts CHANGED
@@ -6,6 +6,8 @@ export * from './async-resource';
6
6
  export * from './condition-variable';
7
7
  export * from './deferred';
8
8
  export * from './emitter';
9
+ export * from './bitmap-work-queue';
10
+ export * from './idle';
9
11
  export * from './pool';
10
12
  export * from './priority-work-queue';
11
13
  export * from './sleep';
package/index.js CHANGED
@@ -1737,6 +1737,166 @@ var ConditionVariable = class {
1737
1737
  }
1738
1738
  };
1739
1739
  //#endregion
1740
+ //#region src/async/idle.ts
1741
+ function requestIdle(fn, opts) {
1742
+ let g = globalThis;
1743
+ let timeout = opts?.timeout;
1744
+ if (typeof g.requestIdleCallback === "function") {
1745
+ let ricOpts;
1746
+ if (timeout !== void 0) ricOpts = { timeout: timeout > 0 ? timeout : 1 };
1747
+ let id = g.requestIdleCallback(fn, ricOpts);
1748
+ return { cancel() {
1749
+ g.cancelIdleCallback?.(id);
1750
+ } };
1751
+ }
1752
+ let delay = 0;
1753
+ if (typeof timeout === "number" && Number.isFinite(timeout) && timeout > 0) delay = timeout;
1754
+ let timer = setTimeout(() => {
1755
+ fn({
1756
+ didTimeout: true,
1757
+ timeRemaining() {
1758
+ return 0;
1759
+ }
1760
+ });
1761
+ }, delay);
1762
+ return { cancel() {
1763
+ clearTimeout(timer);
1764
+ } };
1765
+ }
1766
+ //#endregion
1767
+ //#region src/async/bitmap-work-queue.ts
1768
+ var PRI_ORDER$1 = ["visible", "preload"];
1769
+ function resolveConcurrency$1(value) {
1770
+ if (value === void 0) return 1;
1771
+ let n = Math.floor(value);
1772
+ if (!Number.isFinite(n) || n < 1) return 1;
1773
+ return n;
1774
+ }
1775
+ function emptyLanes$1() {
1776
+ return {
1777
+ visible: [],
1778
+ preload: []
1779
+ };
1780
+ }
1781
+ function createBitmapWorkQueue(opts) {
1782
+ let concurrency = resolveConcurrency$1(opts?.concurrency);
1783
+ let useIdle = opts?.idle !== false;
1784
+ let lanes = emptyLanes$1();
1785
+ let queuedPri = /* @__PURE__ */ new Map();
1786
+ let active = /* @__PURE__ */ new Map();
1787
+ let paused = false;
1788
+ function cancelIdle(job) {
1789
+ job.idleHandle?.cancel();
1790
+ job.idleHandle = void 0;
1791
+ }
1792
+ function removeQueued(id) {
1793
+ let pri = queuedPri.get(id);
1794
+ if (pri === void 0) return void 0;
1795
+ let lane = lanes[pri];
1796
+ let idx = lane.findIndex((job) => job.id === id);
1797
+ queuedPri.delete(id);
1798
+ if (idx < 0) return void 0;
1799
+ let job = lane.splice(idx, 1)[0];
1800
+ cancelIdle(job);
1801
+ return job;
1802
+ }
1803
+ function scheduleIdle(job) {
1804
+ cancelIdle(job);
1805
+ job.idleReady = false;
1806
+ job.idleHandle = requestIdle(() => {
1807
+ job.idleHandle = void 0;
1808
+ if (queuedPri.get(job.id) !== job.pri) return;
1809
+ job.idleReady = true;
1810
+ if (!paused) pump();
1811
+ });
1812
+ }
1813
+ function pickNext() {
1814
+ for (let pri of PRI_ORDER$1) {
1815
+ let lane = lanes[pri];
1816
+ for (let i = 0; i < lane.length; i++) {
1817
+ let job = lane[i];
1818
+ if (!job.idleReady) continue;
1819
+ lane.splice(i, 1);
1820
+ queuedPri.delete(job.id);
1821
+ cancelIdle(job);
1822
+ return job;
1823
+ }
1824
+ }
1825
+ }
1826
+ function pump() {
1827
+ if (paused) return;
1828
+ while (active.size < concurrency) {
1829
+ let job = pickNext();
1830
+ if (!job) return;
1831
+ startJob(job);
1832
+ }
1833
+ }
1834
+ function startJob(job) {
1835
+ let controller = new AbortController();
1836
+ active.set(job.id, {
1837
+ id: job.id,
1838
+ controller
1839
+ });
1840
+ (async () => {
1841
+ try {
1842
+ let signal = controller.signal;
1843
+ if (signal.aborted) return;
1844
+ let bitmap = await createImageBitmap(job.source);
1845
+ if (signal.aborted) {
1846
+ bitmap.close();
1847
+ return;
1848
+ }
1849
+ if (job.run) await job.run({
1850
+ signal,
1851
+ bitmap
1852
+ });
1853
+ else bitmap.close();
1854
+ } catch {} finally {
1855
+ active.delete(job.id);
1856
+ }
1857
+ pump();
1858
+ })();
1859
+ }
1860
+ return {
1861
+ enqueue(job) {
1862
+ if (active.has(job.id)) return false;
1863
+ removeQueued(job.id);
1864
+ let queued = {
1865
+ id: job.id,
1866
+ pri: job.pri,
1867
+ source: job.source,
1868
+ run: job.run,
1869
+ idleReady: true
1870
+ };
1871
+ lanes[job.pri].push(queued);
1872
+ queuedPri.set(job.id, job.pri);
1873
+ if (useIdle && job.pri === "preload") scheduleIdle(queued);
1874
+ else pump();
1875
+ return true;
1876
+ },
1877
+ cancel(id) {
1878
+ if (removeQueued(id)) return true;
1879
+ let running = active.get(id);
1880
+ if (!running) return false;
1881
+ running.controller.abort();
1882
+ return true;
1883
+ },
1884
+ pause() {
1885
+ paused = true;
1886
+ },
1887
+ resume() {
1888
+ paused = false;
1889
+ pump();
1890
+ },
1891
+ get stats() {
1892
+ return {
1893
+ active: active.size,
1894
+ queued: queuedPri.size
1895
+ };
1896
+ }
1897
+ };
1898
+ }
1899
+ //#endregion
1740
1900
  //#region src/async/pool.ts
1741
1901
  var ErrorInfo = class {
1742
1902
  constructor(item, index, error) {
@@ -3298,4 +3458,4 @@ var decompress_exports = /* @__PURE__ */ __exportAll({
3298
3458
  zlib: () => decompress$1
3299
3459
  });
3300
3460
  //#endregion
3301
- export { Adler32, AggregateError, AsyncInterval, AsyncLock, AsyncQueue, AsyncResource, ChecksumMismatchError, ConditionVariable, Crc32, CustomMap, CustomSet, Deferred, DeferredTracked, Deque, Emitter, FlateError, InvalidBlockTypeError, InvalidDistanceError, InvalidHeaderError, InvalidLengthLiteralError, LruMap, LruSet, NotImplementedError, StreamFinishedError, UnexpectedEofError, abs, adler32, asNonNull, assert, assertEndsWith, assertEndsWith as assertsEndsWith, assertHashKey, assertMatches, assertNotNull, assertStartsWith, asyncPool, base64_exports as base64, bitLength, clearUndefinedInPlace, composeMiddlewares, compress_exports as compress, crc32, createPriorityWorkQueue, decompress_exports as decompress, deepMerge, enumerate, euclideanGcd, fromBytes, hex_exports as hex, isBigInt, isBoolean, isFalsy, isFunction, isNotNull, isNotUndefined, isNumber, isObject, isString, isSymbol, isTruthy, max, max2, min, min2, modInv, modPowBinary, noop, objectEntries, objectKeys, parallelMap, sleep, splitOnce, throwNotImplemented, throwUnreachable, timers_exports as timers, toBytes, twoMultiplicity, typed_exports as typed, u8_exports as u8, unknownToError, unsafeCastType, utf8_exports as utf8 };
3461
+ export { Adler32, AggregateError, AsyncInterval, AsyncLock, AsyncQueue, AsyncResource, ChecksumMismatchError, ConditionVariable, Crc32, CustomMap, CustomSet, Deferred, DeferredTracked, Deque, Emitter, FlateError, InvalidBlockTypeError, InvalidDistanceError, InvalidHeaderError, InvalidLengthLiteralError, LruMap, LruSet, NotImplementedError, StreamFinishedError, UnexpectedEofError, abs, adler32, asNonNull, assert, assertEndsWith, assertEndsWith as assertsEndsWith, assertHashKey, assertMatches, assertNotNull, assertStartsWith, asyncPool, base64_exports as base64, bitLength, clearUndefinedInPlace, composeMiddlewares, compress_exports as compress, crc32, createBitmapWorkQueue, createPriorityWorkQueue, decompress_exports as decompress, deepMerge, enumerate, euclideanGcd, fromBytes, hex_exports as hex, isBigInt, isBoolean, isFalsy, isFunction, isNotNull, isNotUndefined, isNumber, isObject, isString, isSymbol, isTruthy, max, max2, min, min2, modInv, modPowBinary, noop, objectEntries, objectKeys, parallelMap, requestIdle, sleep, splitOnce, throwNotImplemented, throwUnreachable, timers_exports as timers, toBytes, twoMultiplicity, typed_exports as typed, u8_exports as u8, unknownToError, unsafeCastType, utf8_exports as utf8 };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@yorozu/utils",
3
3
  "type": "module",
4
- "version": "0.5.3",
4
+ "version": "1.0.25",
5
5
  "description": "quality of life",
6
6
  "license": "MIT",
7
7
  "exports": {