diff --git a/README.md b/README.md index a109dbb..abca023 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,27 @@ console.log(set.size()); // 2 --- +## Benchmarks + +**Tested on:** +- CPU: AMD Ryzen 7 7700 (8-core, up to 5.4 GHz) +- RAM: 32 GB DDR5-5600 +- OS: Windows 11 Pro +- Runtime: Node.js v24.11.1 (tsx) +- Set size: **1,000,000** entities + +| Operation | Throughput (ops/sec) | Per-operation latency | +|------------------------------|----------------------------|-----------------------| +| `add()` | **30.0 – 31.0 million** | ~32–34 ns | +| `has()` | **9.7 – 9.9 million** | ~101–103 ns | +| `get()` | **7.6 – 7.7 million** | ~130–132 ns | +| `remove()` (swap-remove) | **13.0 – 13.9 million** | ~72–77 ns | +| `ensure(id, factory)` | **4.0 million** | ~250 ns | +| `size()` | **>526 million** | **~1.9 ns** | +| `forEach()` (1M elements) | **191–193 passes/sec** | **~5.2 ms** | +| `ids()` / `values()` | **64–65 passes/sec** | ~15.4–15.6 ms | +| Generator iteration | **54–55 passes/sec** | ~18–19 ms | + ## When to Use SparseSet SparseSet excels when: diff --git a/bench/all.ts b/bench/all.ts new file mode 100644 index 0000000..c262dbb --- /dev/null +++ b/bench/all.ts @@ -0,0 +1,110 @@ +import { Bench } from 'tinybench'; +import { SparseSet } from '../dist'; + +function shuffle(array: T[]): T[] { + for (let i = array.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [array[i], array[j]] = [array[j], array[i]]; + } + return array; +} + +const N = 1_000_000; +const LOOP_FACTOR = 10_000; +const ids = Array.from({ length: N }, (_, i) => i); +const shuffledIds = shuffle(ids.slice()); + +// Pre-fill sets +const setForGet = new SparseSet(); +const setForRemove = new SparseSet(); +for (let i = 0; i < N; i++) { + setForGet.add(ids[i], ids[i]); + setForRemove.add(ids[i], ids[i]); +} + +const setForAdd = new SparseSet(); + +let addIndex = 0; +let accessIndex = 0; +let removeIndex = 0; + +const bench = new Bench({ name: 'SparseSet per-method benchmark', time: 1000 }); + +bench + .add(`add() (x${LOOP_FACTOR})`, () => { + for (let k = 0; k < LOOP_FACTOR; k++) { + setForAdd.add(addIndex, addIndex); + addIndex++; + } + }) + .add(`has() (x${LOOP_FACTOR})`, () => { + for (let k = 0; k < LOOP_FACTOR; k++) { + setForGet.has(shuffledIds[accessIndex % N]); + accessIndex++; + } + }) + .add(`get() (x${LOOP_FACTOR})`, () => { + for (let k = 0; k < LOOP_FACTOR; k++) { + setForGet.get(shuffledIds[accessIndex % N]); + accessIndex++; + } + }) + .add(`remove() (x${LOOP_FACTOR})`, () => { + for (let k = 0; k < LOOP_FACTOR; k++) { + const id = shuffledIds[removeIndex % N]; + setForRemove.remove(id); + setForRemove.add(id, id); + removeIndex++; + } + }) + .add(`size() (x${LOOP_FACTOR})`, () => { + for (let k = 0; k < LOOP_FACTOR; k++) { + setForGet.size(); + } + }) + .add('clear() (on 1000 elements)', () => { + const tmp = new SparseSet(); + for (let i = 0; i < 1000; i++) tmp.add(i, i); + tmp.clear(); + }) + .add('iterator()', () => { + let sum = 0; + for (const e of setForGet) sum += e.value; + if (sum === 0) console.log(sum); + }) + .add('ids()', () => { + let sum = 0; + for (const id of setForGet.ids()) sum += id; + if (sum === 0) console.log(sum); + }) + .add('values()', () => { + let sum = 0; + for (const v of setForGet.values()) sum += v; + if (sum === 0) console.log(sum); + }) + .add('entries()', () => { + let sum = 0; + for (const [id, v] of setForGet.entries()) sum += v + id; + if (sum === 0) console.log(sum); + }) + .add('forEach()', () => { + let sum = 0; + setForGet.forEach((v, id) => (sum += v + id)); + if (sum === 0) console.log(sum); + }) + .add(`ensure() (x${LOOP_FACTOR})`, () => { + for (let k = 0; k < LOOP_FACTOR; k++) { + setForGet.ensure(N + accessIndex, () => 999); + accessIndex++; + } + }) + .add(`tryGetIndex() (x${LOOP_FACTOR})`, () => { + for (let k = 0; k < LOOP_FACTOR; k++) { + setForGet.tryGetIndex(shuffledIds[accessIndex % N]); + accessIndex++; + } + }); + +await bench.run(); + +console.table(bench.table()); \ No newline at end of file diff --git a/package.json b/package.json index a0fddf7..b852887 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,8 @@ "lint": "eslint src --ext .ts", "lint:fix": "eslint src --ext .ts --fix", "format": "prettier --write ./src/**/*.ts", - "test": "jest" + "test": "jest", + "bench": "tsx ./bench/all.ts" }, "devDependencies": { "@jest/globals": "^30.2.0", @@ -67,8 +68,10 @@ "jest": "^30.2.0", "prettier": "^3.7.3", "rollup-plugin-typescript-paths": "^1.5.0", + "tinybench": "^6.0.0", "ts-jest": "^29.4.6", "tslib": "^2.8.1", + "tsx": "^4.21.0", "typescript": "~5.9.3", "vite": "^7.2.4", "vite-plugin-dts": "^4.5.4", diff --git a/src/sparse_set.test.ts b/src/sparse_set.test.ts index d2d99c2..da308f0 100644 --- a/src/sparse_set.test.ts +++ b/src/sparse_set.test.ts @@ -126,14 +126,14 @@ describe("SparseSet", () => { }); test("size returns correct number of elements", () => { - expect(set.size()).toBe(0); + expect(set.size).toBe(0); set.add(1, 10); set.add(2, 20); - expect(set.size()).toBe(2); + expect(set.size).toBe(2); set.remove(1); - expect(set.size()).toBe(1); + expect(set.size).toBe(1); }); test("clear removes all elements", () => { @@ -143,7 +143,7 @@ describe("SparseSet", () => { set.clear(); - expect(set.size()).toBe(0); + expect(set.size).toBe(0); expect(set.has(1)).toBe(false); expect(set.has(2)).toBe(false); expect(set.has(3)).toBe(false); @@ -226,5 +226,4 @@ describe("SparseSet", () => { test("tryGetIndex returns -1 for missing id", () => { expect(set.tryGetIndex(123)).toBe(-1); }); - }); diff --git a/src/sparse_set.ts b/src/sparse_set.ts index 9b61cb1..32b078a 100644 --- a/src/sparse_set.ts +++ b/src/sparse_set.ts @@ -15,6 +15,15 @@ export class SparseSet { private dense: number[] = []; private data: V[] = []; + private growSparse(minId: number): void { + if (minId < this.sparse.length) return; + + let newLen = this.sparse.length === 0 ? 1024 : this.sparse.length * 2; + while (newLen <= minId) newLen *= 2; + + this.sparse.length = newLen; + } + /** * Checks whether an item with the given id exists in the set. * @@ -23,11 +32,7 @@ export class SparseSet { */ public has(id: number): boolean { const index = this.sparse[id]; - return ( - index !== undefined && - index < this.dense.length && - this.dense[index] === id - ); + return index !== undefined && this.dense[index] === id; } /** @@ -38,16 +43,10 @@ export class SparseSet { */ public get(id: number): V | null { const index = this.sparse[id]; - if ( - index === undefined || - index >= this.dense.length || - this.dense[index] !== id - ) { - return null; - } - return this.data[index]; + return index !== undefined && this.dense[index] === id + ? this.data[index] + : null; } - /** * Adds or updates an element with the specified id. * If the id already exists, its value is overwritten. @@ -58,23 +57,17 @@ export class SparseSet { */ public add(id: number, value: V): V { const existing = this.sparse[id]; - if ( - existing !== undefined && - existing < this.dense.length && - this.dense[existing] === id - ) { + if (existing !== undefined && this.dense[existing] === id) { this.data[existing] = value; return value; } const index = this.dense.length; + this.dense[index] = id; this.data[index] = value; - if (this.sparse.length <= id) { - this.sparse.length = id + 1; - } - + this.growSparse(id); this.sparse[id] = index; return value; @@ -88,13 +81,7 @@ export class SparseSet { */ public remove(id: number): void { const index = this.sparse[id]; - if ( - index === undefined || - index >= this.dense.length || - this.dense[index] !== id - ) { - return; - } + if (index === undefined || this.dense[index] !== id) return; const lastIndex = this.dense.length - 1; const lastId = this.dense[lastIndex]; @@ -130,7 +117,7 @@ export class SparseSet { * * @returns Total element count. */ - public size(): number { + public get size(): number { return this.dense.length; } @@ -191,13 +178,21 @@ export class SparseSet { * @returns The existing or newly created value. */ public ensure(id: number, factory: () => V): V { - const index = this.sparse[id]; + let index = this.sparse[id]; if (index !== undefined && this.dense[index] === id) { return this.data[index]; } - const v = factory(); - this.add(id, v); - return v; + + const value = factory(); + index = this.dense.length; + + this.dense[index] = id; + this.data[index] = value; + + this.growSparse(id); + this.sparse[id] = index; + + return value; } /** diff --git a/yarn.lock b/yarn.lock index 3b85c1d..1c14943 100644 --- a/yarn.lock +++ b/yarn.lock @@ -297,131 +297,261 @@ resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz#80fcbe36130e58b7670511e888b8e88a259ed76c" integrity sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA== +"@esbuild/aix-ppc64@0.27.0": + version "0.27.0" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.27.0.tgz#1d8be43489a961615d49e037f1bfa0f52a773737" + integrity sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A== + "@esbuild/android-arm64@0.25.12": version "0.25.12" resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz#8aa4965f8d0a7982dc21734bf6601323a66da752" integrity sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg== +"@esbuild/android-arm64@0.27.0": + version "0.27.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.27.0.tgz#bd1763194aad60753fa3338b1ba9bda974b58724" + integrity sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ== + "@esbuild/android-arm@0.25.12": version "0.25.12" resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.12.tgz#300712101f7f50f1d2627a162e6e09b109b6767a" integrity sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg== +"@esbuild/android-arm@0.27.0": + version "0.27.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.27.0.tgz#69c7b57f02d3b3618a5ba4f82d127b57665dc397" + integrity sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ== + "@esbuild/android-x64@0.25.12": version "0.25.12" resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.12.tgz#87dfb27161202bdc958ef48bb61b09c758faee16" integrity sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg== +"@esbuild/android-x64@0.27.0": + version "0.27.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.27.0.tgz#6ea22b5843acb23243d0126c052d7d3b6a11ca90" + integrity sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q== + "@esbuild/darwin-arm64@0.25.12": version "0.25.12" resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz#79197898ec1ff745d21c071e1c7cc3c802f0c1fd" integrity sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg== +"@esbuild/darwin-arm64@0.27.0": + version "0.27.0" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.27.0.tgz#5ad7c02bc1b1a937a420f919afe40665ba14ad1e" + integrity sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg== + "@esbuild/darwin-x64@0.25.12": version "0.25.12" resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz#146400a8562133f45c4d2eadcf37ddd09718079e" integrity sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA== +"@esbuild/darwin-x64@0.27.0": + version "0.27.0" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.27.0.tgz#48470c83c5fd6d1fc7c823c2c603aeee96e101c9" + integrity sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g== + "@esbuild/freebsd-arm64@0.25.12": version "0.25.12" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz#1c5f9ba7206e158fd2b24c59fa2d2c8bb47ca0fe" integrity sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg== +"@esbuild/freebsd-arm64@0.27.0": + version "0.27.0" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.0.tgz#d5a8effd8b0be7be613cd1009da34d629d4c2457" + integrity sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw== + "@esbuild/freebsd-x64@0.25.12": version "0.25.12" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz#ea631f4a36beaac4b9279fa0fcc6ca29eaeeb2b3" integrity sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ== +"@esbuild/freebsd-x64@0.27.0": + version "0.27.0" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.27.0.tgz#9bde638bda31aa244d6d64dbafafb41e6e799bcc" + integrity sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g== + "@esbuild/linux-arm64@0.25.12": version "0.25.12" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz#e1066bce58394f1b1141deec8557a5f0a22f5977" integrity sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ== +"@esbuild/linux-arm64@0.27.0": + version "0.27.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.27.0.tgz#96008c3a207d8ca495708db714c475ea5bf7e2af" + integrity sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ== + "@esbuild/linux-arm@0.25.12": version "0.25.12" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz#452cd66b20932d08bdc53a8b61c0e30baf4348b9" integrity sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw== +"@esbuild/linux-arm@0.27.0": + version "0.27.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.27.0.tgz#9b47cb0f222e567af316e978c7f35307db97bc0e" + integrity sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ== + "@esbuild/linux-ia32@0.25.12": version "0.25.12" resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz#b24f8acc45bcf54192c7f2f3be1b53e6551eafe0" integrity sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA== +"@esbuild/linux-ia32@0.27.0": + version "0.27.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.27.0.tgz#d1e1e38d406cbdfb8a49f4eca0c25bbc344e18cc" + integrity sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw== + "@esbuild/linux-loong64@0.25.12": version "0.25.12" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz#f9cfffa7fc8322571fbc4c8b3268caf15bd81ad0" integrity sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng== +"@esbuild/linux-loong64@0.27.0": + version "0.27.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.27.0.tgz#c13bc6a53e3b69b76f248065bebee8415b44dfce" + integrity sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg== + "@esbuild/linux-mips64el@0.25.12": version "0.25.12" resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz#575a14bd74644ffab891adc7d7e60d275296f2cd" integrity sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw== +"@esbuild/linux-mips64el@0.27.0": + version "0.27.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.27.0.tgz#05f8322eb0a96ce1bfbc59691abe788f71e2d217" + integrity sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg== + "@esbuild/linux-ppc64@0.25.12": version "0.25.12" resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz#75b99c70a95fbd5f7739d7692befe60601591869" integrity sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA== +"@esbuild/linux-ppc64@0.27.0": + version "0.27.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.27.0.tgz#6fc5e7af98b4fb0c6a7f0b73ba837ce44dc54980" + integrity sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA== + "@esbuild/linux-riscv64@0.25.12": version "0.25.12" resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz#2e3259440321a44e79ddf7535c325057da875cd6" integrity sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w== +"@esbuild/linux-riscv64@0.27.0": + version "0.27.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.27.0.tgz#508afa9f69a3f97368c0bf07dd894a04af39d86e" + integrity sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ== + "@esbuild/linux-s390x@0.25.12": version "0.25.12" resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz#17676cabbfe5928da5b2a0d6df5d58cd08db2663" integrity sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg== +"@esbuild/linux-s390x@0.27.0": + version "0.27.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.27.0.tgz#21fda656110ee242fc64f87a9e0b0276d4e4ec5b" + integrity sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w== + "@esbuild/linux-x64@0.25.12": version "0.25.12" resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz#0583775685ca82066d04c3507f09524d3cd7a306" integrity sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw== +"@esbuild/linux-x64@0.27.0": + version "0.27.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.27.0.tgz#1758a85dcc09b387fd57621643e77b25e0ccba59" + integrity sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw== + "@esbuild/netbsd-arm64@0.25.12": version "0.25.12" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz#f04c4049cb2e252fe96b16fed90f70746b13f4a4" integrity sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg== +"@esbuild/netbsd-arm64@0.27.0": + version "0.27.0" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.0.tgz#a0131159f4db6e490da35cc4bb51ef0d03b7848a" + integrity sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w== + "@esbuild/netbsd-x64@0.25.12": version "0.25.12" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz#77da0d0a0d826d7c921eea3d40292548b258a076" integrity sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ== +"@esbuild/netbsd-x64@0.27.0": + version "0.27.0" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.27.0.tgz#6f4877d7c2ba425a2b80e4330594e0b43caa2d7d" + integrity sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA== + "@esbuild/openbsd-arm64@0.25.12": version "0.25.12" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz#6296f5867aedef28a81b22ab2009c786a952dccd" integrity sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A== +"@esbuild/openbsd-arm64@0.27.0": + version "0.27.0" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.0.tgz#cbefbd4c2f375cebeb4f965945be6cf81331bd01" + integrity sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ== + "@esbuild/openbsd-x64@0.25.12": version "0.25.12" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz#f8d23303360e27b16cf065b23bbff43c14142679" integrity sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw== +"@esbuild/openbsd-x64@0.27.0": + version "0.27.0" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.27.0.tgz#31fa9e8649fc750d7c2302c8b9d0e1547f57bc84" + integrity sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A== + "@esbuild/openharmony-arm64@0.25.12": version "0.25.12" resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz#49e0b768744a3924be0d7fd97dd6ce9b2923d88d" integrity sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg== +"@esbuild/openharmony-arm64@0.27.0": + version "0.27.0" + resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.0.tgz#03727780f1fdf606e7b56193693a715d9f1ee001" + integrity sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA== + "@esbuild/sunos-x64@0.25.12": version "0.25.12" resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz#a6ed7d6778d67e528c81fb165b23f4911b9b13d6" integrity sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w== +"@esbuild/sunos-x64@0.27.0": + version "0.27.0" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.27.0.tgz#866a35f387234a867ced35af8906dfffb073b9ff" + integrity sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA== + "@esbuild/win32-arm64@0.25.12": version "0.25.12" resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz#9ac14c378e1b653af17d08e7d3ce34caef587323" integrity sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg== +"@esbuild/win32-arm64@0.27.0": + version "0.27.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.27.0.tgz#53de43a9629b8a34678f28cd56cc104db1b67abb" + integrity sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg== + "@esbuild/win32-ia32@0.25.12": version "0.25.12" resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz#918942dcbbb35cc14fca39afb91b5e6a3d127267" integrity sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ== +"@esbuild/win32-ia32@0.27.0": + version "0.27.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.27.0.tgz#924d2aed8692fea5d27bfb6500f9b8b9c1a34af4" + integrity sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ== + "@esbuild/win32-x64@0.25.12": version "0.25.12" resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz#9bdad8176be7811ad148d1f8772359041f46c6c5" integrity sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA== +"@esbuild/win32-x64@0.27.0": + version "0.27.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.27.0.tgz#64995295227e001f2940258617c6674efb3ac48d" + integrity sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg== + "@eslint-community/eslint-utils@^4.7.0", "@eslint-community/eslint-utils@^4.8.0": version "4.9.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz#7308df158e064f0dd8b8fdb58aa14fa2a7f913b3" @@ -1891,6 +2021,38 @@ esbuild@^0.25.0: "@esbuild/win32-ia32" "0.25.12" "@esbuild/win32-x64" "0.25.12" +esbuild@~0.27.0: + version "0.27.0" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.27.0.tgz#db983bed6f76981361c92f50cf6a04c66f7b3e1d" + integrity sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA== + optionalDependencies: + "@esbuild/aix-ppc64" "0.27.0" + "@esbuild/android-arm" "0.27.0" + "@esbuild/android-arm64" "0.27.0" + "@esbuild/android-x64" "0.27.0" + "@esbuild/darwin-arm64" "0.27.0" + "@esbuild/darwin-x64" "0.27.0" + "@esbuild/freebsd-arm64" "0.27.0" + "@esbuild/freebsd-x64" "0.27.0" + "@esbuild/linux-arm" "0.27.0" + "@esbuild/linux-arm64" "0.27.0" + "@esbuild/linux-ia32" "0.27.0" + "@esbuild/linux-loong64" "0.27.0" + "@esbuild/linux-mips64el" "0.27.0" + "@esbuild/linux-ppc64" "0.27.0" + "@esbuild/linux-riscv64" "0.27.0" + "@esbuild/linux-s390x" "0.27.0" + "@esbuild/linux-x64" "0.27.0" + "@esbuild/netbsd-arm64" "0.27.0" + "@esbuild/netbsd-x64" "0.27.0" + "@esbuild/openbsd-arm64" "0.27.0" + "@esbuild/openbsd-x64" "0.27.0" + "@esbuild/openharmony-arm64" "0.27.0" + "@esbuild/sunos-x64" "0.27.0" + "@esbuild/win32-arm64" "0.27.0" + "@esbuild/win32-ia32" "0.27.0" + "@esbuild/win32-x64" "0.27.0" + escalade@^3.1.1, escalade@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" @@ -2176,6 +2338,13 @@ get-stream@^6.0.0: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== +get-tsconfig@^4.7.5: + version "4.13.0" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.13.0.tgz#fcdd991e6d22ab9a600f00e91c318707a5d9a0d7" + integrity sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ== + dependencies: + resolve-pkg-maps "^1.0.0" + glob-parent@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" @@ -3303,6 +3472,11 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== +resolve-pkg-maps@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" + integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== + resolve@^1.22.1, resolve@~1.22.1, resolve@~1.22.2: version "1.22.11" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.11.tgz#aad857ce1ffb8bfa9b0b1ac29f1156383f68c262" @@ -3533,6 +3707,11 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" +tinybench@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-6.0.0.tgz#890309d74e0c3f60b20def20295bfd937c1d7521" + integrity sha512-BWlWpVbbZXaYjRV0twGLNQO00Zj4HA/sjLOQP2IvzQqGwRGp+2kh7UU3ijyJ3ywFRogYDRbiHDMrUOfaMnN56g== + tinyglobby@^0.2.15: version "0.2.15" resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.15.tgz#e228dd1e638cea993d2fdb4fcd2d4602a79951c2" @@ -3583,6 +3762,16 @@ tslib@^2.4.0, tslib@^2.8.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== +tsx@^4.21.0: + version "4.21.0" + resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.21.0.tgz#32aa6cf17481e336f756195e6fe04dae3e6308b1" + integrity sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw== + dependencies: + esbuild "~0.27.0" + get-tsconfig "^4.7.5" + optionalDependencies: + fsevents "~2.3.3" + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"