├── .gitignore ├── README.md ├── example ├── context.ts ├── main.ts └── struct-buffer.comp.wgsl ├── index.html ├── package.json ├── pnpm-lock.yaml ├── src ├── StructBuffer.test.ts ├── StructBuffer.ts ├── index.ts ├── polyfill.ts └── vite-env.d.ts ├── tsconfig.json └── vite.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wgsl-struct-buffer 2 | 3 | 一个给`WGSL's Struct`提供`BufferView`的小工具, 方便 ComputeShader 中复杂数据结构表示和编辑 4 | 5 | - 支持 f16(虽然还没有浏览器支持 shader-f16 扩展) 6 | - 支持 Struct/Array 嵌套, 7 | - 支持 ArrayRumtimeSized (需要位于 Struct 末尾, 且只有一个) 8 | - TS 类型友好, 支持类型检查+提示 9 | 10 | ```ts 11 | type PrimitiveNumber = 'f16' | 'f32' | 'u32' | 'i32'; 12 | type PrimitiveVector = `${'vec2' | 'vec3' | 'vec4'}${'f' | 'h' | 'u' | 'i'}`; 13 | type PrimitiveMatrix = `${'mat3x3' | 'mat4x4'}${'f' | 'h'}`; 14 | type PrimitiveTypedArray = PrimitiveVector | PrimitiveMatrix; 15 | type Primitive = PrimitiveNumber | PrimitiveTypedArray; 16 | type Array = [struct: Struct, length: number, runtimeSized?: boolean]; 17 | type Struct = { [k: string]: Primitive | Array | Struct }; 18 | ``` 19 | 20 | # 使用 21 | 22 | ```sh 23 | > pnpm i -S wgsl-struct-buffer 24 | ``` 25 | 26 | ```ts 27 | import { wgsl } from 'wgsl-struct-buffer'; 28 | 29 | const { view, buffer, struct } = new wgsl.StructBuffer({ 30 | ambient: 'vec3f', // vec{2,3,4}{f,h,u,i} 31 | lightCount: 'u32', // f32, f16, u32, i32 32 | lights: [ 33 | { 34 | position: 'vec3f', 35 | range: 'f32', 36 | color: 'vec3f', 37 | intensity: 'f32', 38 | }, 39 | 4, 40 | ], 41 | }); 42 | view.ambient.set([0, 0, 0]); 43 | view.lightCount = 4; 44 | view.lights.forEach(light => { 45 | light.position.set([1, 2, 3]); 46 | light.color.set([1, 1, 1]); 47 | light.range = 10; 48 | light.intensity = 0.8; 49 | }); 50 | console.log(buffer); 51 | console.log(wgsl.stringifyStruct('LightInfo', struct)); 52 | /** output 53 | struct LightInfo_lights { 54 | position: vec3f, 55 | range: f32, 56 | color: vec3f, 57 | intensity: f32, 58 | }; 59 | struct LightInfo { 60 | ambient: vec3f, 61 | lightCount: u32, 62 | lights: array, 63 | }; 64 | */ 65 | ``` 66 | 67 | 启用`f16` 68 | 69 | ```ts 70 | import { wgsl, setPolyfill } from 'wgsl-struct-buffer'; 71 | import * as polyfill from '@petamoriken/float16'; 72 | 73 | setPolyfill(polyfill); 74 | ``` 75 | 76 | # 赞助 77 | 78 | 如果项目对您有帮助,欢迎打赏 79 | 80 | 赞赏码 81 | 82 | 感谢各位支持~~ 83 | 84 | # License 85 | 86 | MIT 欢迎学习交流 👏🏻 87 | -------------------------------------------------------------------------------- /example/context.ts: -------------------------------------------------------------------------------- 1 | export let adapter: GPUAdapter; 2 | export let device: GPUDevice; 3 | export let queue: GPUQueue; 4 | export let canvasCtx: GPUCanvasContext; 5 | export let canvasFormat: GPUTextureFormat; 6 | 7 | export async function initContext(canvas: HTMLCanvasElement) { 8 | // 🏭 Entry to WebGPU 9 | const entry: GPU = navigator.gpu; 10 | if (!entry) return false; 11 | 12 | // 🔌 Physical Device Adapter 13 | adapter = (await entry.requestAdapter({ forceFallbackAdapter: false }))!; 14 | 15 | adapter.requestAdapterInfo?.().then(console.log); 16 | // 💻 Logical Device 17 | device = await adapter.requestDevice(); 18 | queue = device.queue; 19 | canvasCtx = canvas.getContext('webgpu')!; 20 | canvasFormat = navigator.gpu.getPreferredCanvasFormat(); 21 | 22 | if (!canvasCtx) throw new Error('get webgpu context fail'); 23 | } 24 | 25 | const align = (len: number, alignment: number = 4) => { 26 | return (len + (alignment - 1)) & ~(alignment - 1); 27 | }; 28 | 29 | export function createBuffer( 30 | data: Float32Array | Uint32Array | Uint8Array | Uint16Array, 31 | usage: GPUFlagsConstant, 32 | mappedAtCreation = false, 33 | alignment = 4, 34 | ) { 35 | const buffer = device.createBuffer({ 36 | usage, 37 | size: align(data.byteLength, alignment), 38 | mappedAtCreation, 39 | }); 40 | if (mappedAtCreation) { 41 | // @ts-ignore 42 | new data.constructor(buffer.getMappedRange()).set(data); 43 | buffer.unmap(); 44 | } 45 | return buffer; 46 | } 47 | -------------------------------------------------------------------------------- /example/main.ts: -------------------------------------------------------------------------------- 1 | import { device, initContext, queue, createBuffer } from './context'; 2 | import { wgsl, setPolyfill } from '../src'; 3 | import * as polyfill from '@petamoriken/float16'; 4 | import COMPUTE_SHADER from './struct-buffer.comp.wgsl?raw'; 5 | 6 | setPolyfill(polyfill); 7 | 8 | function arrayEq(a: ArrayLike, b: ArrayLike) { 9 | for (let i = 0; i < a.length; i++) { 10 | if (a[i] != b[i]) return false; 11 | } 12 | return true; 13 | } 14 | 15 | async function main() { 16 | const canvas = document.getElementById('gfx') as HTMLCanvasElement; 17 | await initContext(canvas); 18 | 19 | const subarray = { 20 | f32_: 'f32', 21 | i32_: 'i32', 22 | } satisfies wgsl.Struct; 23 | const substruct = { 24 | vec2_0: 'vec2f', 25 | vec2_1: 'vec2f', 26 | subarray: [subarray, 2], 27 | } satisfies wgsl.Struct; 28 | const struct = new wgsl.StructBuffer({ 29 | u32_: 'u32', 30 | i32_: 'i32', 31 | f32_: 'f32', 32 | vec2_: 'vec2f', 33 | vec3_: 'vec3f', 34 | vec4_: 'vec4f', 35 | mat3_: 'mat3x3f', 36 | mat4_: 'mat4x4f', 37 | 38 | substruct, 39 | subarray: [substruct, 2], 40 | }); 41 | console.log(wgsl.stringifyStruct('Test', struct.struct)); 42 | const bindgroupLayout = device.createBindGroupLayout({ 43 | entries: [{ binding: 0, buffer: { type: 'storage' }, visibility: GPUShaderStage.COMPUTE }], 44 | }); 45 | const pipeline = device.createComputePipeline({ 46 | layout: device.createPipelineLayout({ bindGroupLayouts: [bindgroupLayout] }), 47 | compute: { module: device.createShaderModule({ code: COMPUTE_SHADER }), entryPoint: 'main' }, 48 | }); 49 | const gpuBuffer = createBuffer(struct.buffer, GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC); 50 | const stagingBuffer = createBuffer( 51 | struct.buffer, 52 | GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST, 53 | ); 54 | 55 | const bindgroup = device.createBindGroup({ 56 | layout: bindgroupLayout, 57 | entries: [{ binding: 0, resource: { buffer: gpuBuffer } }], 58 | }); 59 | 60 | const commandEncoder = device.createCommandEncoder(); 61 | const passEncoder = commandEncoder.beginComputePass(); 62 | passEncoder.setPipeline(pipeline); 63 | passEncoder.setBindGroup(0, bindgroup); 64 | passEncoder.dispatchWorkgroups(1); 65 | passEncoder.end(); 66 | commandEncoder.copyBufferToBuffer(gpuBuffer, 0, stagingBuffer, 0, stagingBuffer.size); 67 | queue.submit([commandEncoder.finish()]); 68 | 69 | await stagingBuffer.mapAsync(GPUMapMode.READ); 70 | struct.buffer.set(new Uint8Array(stagingBuffer.getMappedRange())); 71 | stagingBuffer.unmap(); 72 | 73 | console.log(struct.view); 74 | console.log(struct.buffer); 75 | const { view } = struct; 76 | const { assert } = console; 77 | 78 | assert(view.u32_ === 1); 79 | assert(view.i32_ === 2); 80 | assert(view.f32_ === 3); 81 | 82 | assert(arrayEq(view.vec2_, [4, 5])); 83 | assert(arrayEq(view.vec3_, [6, 7, 8])); 84 | assert(arrayEq(view.vec4_, [9, 10, 11, 12])); 85 | // prettier-ignore 86 | assert(arrayEq(view.mat3_, [ 87 | 13.0, 14.0, 15.0, 0, 88 | 16.0, 17.0, 18.0, 0, 89 | 19.0, 20.0, 21.0, 0, 90 | ]),); 91 | // prettier-ignore 92 | assert(arrayEq(view.mat4_, [ 93 | 22.0, 23.0, 24.0, 25.0, 94 | 26.0, 27.0, 28.0, 29.0, 95 | 30.0, 31.0, 32.0, 33.0, 96 | 34.0, 35.0, 36.0, 37.0, 97 | ])); 98 | 99 | assert(arrayEq(view.subarray[0].vec2_0, [46.0, 47.0])); 100 | assert(arrayEq(view.subarray[0].vec2_1, [48.0, 49.0])); 101 | assert(view.subarray[0].subarray[0].f32_ == 50); 102 | assert(view.subarray[0].subarray[0].i32_ == 51); 103 | assert(view.subarray[0].subarray[1].f32_ == 52); 104 | assert(view.subarray[0].subarray[1].i32_ == 53); 105 | 106 | assert(arrayEq(view.subarray[1].vec2_0, [54.0, 55.0])); 107 | assert(arrayEq(view.subarray[1].vec2_1, [56.0, 57.0])); 108 | assert(view.subarray[1].subarray[0].f32_ == 58); 109 | assert(view.subarray[1].subarray[0].i32_ == 59); 110 | assert(view.subarray[1].subarray[1].f32_ == 60); 111 | assert(view.subarray[1].subarray[1].i32_ == 61); 112 | } 113 | 114 | main(); 115 | -------------------------------------------------------------------------------- /example/struct-buffer.comp.wgsl: -------------------------------------------------------------------------------- 1 | struct Subarray { 2 | f32_: f32, 3 | i32_: i32, 4 | } 5 | struct Substruct { 6 | vec2_0: vec2, 7 | vec2_1: vec2, 8 | subarray: array, 9 | } 10 | 11 | struct Test { 12 | u32_: u32, 13 | i32_: i32, 14 | f32_: f32, 15 | vec2_: vec2, 16 | vec3_: vec3, 17 | vec4_: vec4, 18 | mat3_: mat3x3, 19 | mat4_: mat4x4, 20 | substruct: Substruct, 21 | subarray: array, 22 | } 23 | 24 | @group(0) @binding(0) var view: Test; 25 | 26 | @compute @workgroup_size(1) 27 | fn main(@builtin(global_invocation_id) id: vec3) { 28 | view.u32_ = 1u; 29 | view.i32_ = 2; 30 | view.f32_ = 3.0; 31 | view.vec2_ = vec2(4.0, 5.0); 32 | view.vec3_ = vec3(6.0, 7.0, 8.0); 33 | view.vec4_ = vec4(9.0, 10.0, 11.0, 12.0); 34 | view.mat3_ = mat3x3( 35 | 13.0, 14.0, 15.0, 36 | 16.0, 17.0, 18.0, 37 | 19.0, 20.0, 21.0, 38 | ); 39 | view.mat4_ = mat4x4( 40 | 22.0, 23.0, 24.0, 25.0, 41 | 26.0, 27.0, 28.0, 29.0, 42 | 30.0, 31.0, 32.0, 33.0, 43 | 34.0, 35.0, 36.0, 37.0, 44 | ); 45 | view.substruct.vec2_0 = vec2(38.0, 39.0); 46 | view.substruct.vec2_1 = vec2(40.0, 41.0); 47 | view.substruct.subarray[0].f32_ = 42.0; 48 | view.substruct.subarray[0].i32_ = 43; 49 | view.substruct.subarray[1].f32_ = 44.0; 50 | view.substruct.subarray[1].i32_ = 45; 51 | 52 | view.subarray[0].vec2_0 = vec2(46.0, 47.0); 53 | view.subarray[0].vec2_1 = vec2(48.0, 49.0); 54 | view.subarray[0].subarray[0].f32_ = 50.0; 55 | view.subarray[0].subarray[0].i32_ = 51; 56 | view.subarray[0].subarray[1].f32_ = 52.0; 57 | view.subarray[0].subarray[1].i32_ = 53; 58 | 59 | view.subarray[1].vec2_0 = vec2(54.0, 55.0); 60 | view.subarray[1].vec2_1 = vec2(56.0, 57.0); 61 | view.subarray[1].subarray[0].f32_ = 58.0; 62 | view.subarray[1].subarray[0].i32_ = 59; 63 | view.subarray[1].subarray[1].f32_ = 60.0; 64 | view.subarray[1].subarray[1].i32_ = 61; 65 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | wgsl-struct-buffer 8 | 9 | 10 |
请打开DevTool查看console.log输出
11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wgsl-struct-buffer", 3 | "version": "0.0.1", 4 | "description": "struct buffer view for wgsl's struct", 5 | "author": "deepkolos@qq.com", 6 | "keywords": [ 7 | "struct", 8 | "wgsl", 9 | "bufferview" 10 | ], 11 | "type": "module", 12 | "main": "./dist/wgsl-struct-buffer.umd.cjs", 13 | "module": "./dist/wgsl-struct-buffer.js", 14 | "types": "./dist/StructBuffer.d.ts", 15 | "exports": { 16 | ".": { 17 | "import": "./dist/wgsl-struct-buffer.js", 18 | "require": "./dist/wgsl-struct-buffer.umd.cjs", 19 | "types": "./dist/StructBuffer.d.ts" 20 | } 21 | }, 22 | "files": [ 23 | "dist", 24 | "README.md", 25 | "package.json" 26 | ], 27 | "scripts": { 28 | "dev": "vite", 29 | "build": "vite build", 30 | "preview": "vite preview", 31 | "test": "vitest", 32 | "bench": "vitest bench", 33 | "coverage": "vitest run --coverage", 34 | "prepublishOnly": "pnpm build" 35 | }, 36 | "sideEffects": false, 37 | "devDependencies": { 38 | "@webgpu/types": "latest", 39 | "typescript": "^5.0.2", 40 | "vite": "^4.3.2", 41 | "vite-plugin-dts": "^2.3.0", 42 | "vitest": "^0.31.1" 43 | }, 44 | "dependencies": { 45 | "@petamoriken/float16": "^3.8.0" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '6.0' 2 | 3 | dependencies: 4 | '@petamoriken/float16': 5 | specifier: ^3.8.0 6 | version: 3.8.0 7 | 8 | devDependencies: 9 | '@webgpu/types': 10 | specifier: latest 11 | version: 0.1.32 12 | typescript: 13 | specifier: ^5.0.2 14 | version: 5.0.2 15 | vite: 16 | specifier: ^4.3.2 17 | version: 4.3.2(@types/node@20.2.3) 18 | vite-plugin-dts: 19 | specifier: ^2.3.0 20 | version: 2.3.0(vite@4.3.2) 21 | vitest: 22 | specifier: ^0.31.1 23 | version: 0.31.1 24 | 25 | packages: 26 | 27 | /@babel/helper-string-parser@7.21.5: 28 | resolution: {integrity: sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==} 29 | engines: {node: '>=6.9.0'} 30 | dev: true 31 | 32 | /@babel/helper-validator-identifier@7.19.1: 33 | resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} 34 | engines: {node: '>=6.9.0'} 35 | dev: true 36 | 37 | /@babel/parser@7.21.9: 38 | resolution: {integrity: sha512-q5PNg/Bi1OpGgx5jYlvWZwAorZepEudDMCLtj967aeS7WMont7dUZI46M2XwcIQqvUlMxWfdLFu4S/qSxeUu5g==} 39 | engines: {node: '>=6.0.0'} 40 | hasBin: true 41 | dependencies: 42 | '@babel/types': 7.21.5 43 | dev: true 44 | 45 | /@babel/types@7.21.5: 46 | resolution: {integrity: sha512-m4AfNvVF2mVC/F7fDEdH2El3HzUg9It/XsCxZiOTTA3m3qYfcSVSbTfM6Q9xG+hYDniZssYhlXKKUMD5m8tF4Q==} 47 | engines: {node: '>=6.9.0'} 48 | dependencies: 49 | '@babel/helper-string-parser': 7.21.5 50 | '@babel/helper-validator-identifier': 7.19.1 51 | to-fast-properties: 2.0.0 52 | dev: true 53 | 54 | /@esbuild/android-arm64@0.17.19: 55 | resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==} 56 | engines: {node: '>=12'} 57 | cpu: [arm64] 58 | os: [android] 59 | requiresBuild: true 60 | dev: true 61 | optional: true 62 | 63 | /@esbuild/android-arm@0.17.19: 64 | resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==} 65 | engines: {node: '>=12'} 66 | cpu: [arm] 67 | os: [android] 68 | requiresBuild: true 69 | dev: true 70 | optional: true 71 | 72 | /@esbuild/android-x64@0.17.19: 73 | resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==} 74 | engines: {node: '>=12'} 75 | cpu: [x64] 76 | os: [android] 77 | requiresBuild: true 78 | dev: true 79 | optional: true 80 | 81 | /@esbuild/darwin-arm64@0.17.19: 82 | resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==} 83 | engines: {node: '>=12'} 84 | cpu: [arm64] 85 | os: [darwin] 86 | requiresBuild: true 87 | dev: true 88 | optional: true 89 | 90 | /@esbuild/darwin-x64@0.17.19: 91 | resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==} 92 | engines: {node: '>=12'} 93 | cpu: [x64] 94 | os: [darwin] 95 | requiresBuild: true 96 | dev: true 97 | optional: true 98 | 99 | /@esbuild/freebsd-arm64@0.17.19: 100 | resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==} 101 | engines: {node: '>=12'} 102 | cpu: [arm64] 103 | os: [freebsd] 104 | requiresBuild: true 105 | dev: true 106 | optional: true 107 | 108 | /@esbuild/freebsd-x64@0.17.19: 109 | resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==} 110 | engines: {node: '>=12'} 111 | cpu: [x64] 112 | os: [freebsd] 113 | requiresBuild: true 114 | dev: true 115 | optional: true 116 | 117 | /@esbuild/linux-arm64@0.17.19: 118 | resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==} 119 | engines: {node: '>=12'} 120 | cpu: [arm64] 121 | os: [linux] 122 | requiresBuild: true 123 | dev: true 124 | optional: true 125 | 126 | /@esbuild/linux-arm@0.17.19: 127 | resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==} 128 | engines: {node: '>=12'} 129 | cpu: [arm] 130 | os: [linux] 131 | requiresBuild: true 132 | dev: true 133 | optional: true 134 | 135 | /@esbuild/linux-ia32@0.17.19: 136 | resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==} 137 | engines: {node: '>=12'} 138 | cpu: [ia32] 139 | os: [linux] 140 | requiresBuild: true 141 | dev: true 142 | optional: true 143 | 144 | /@esbuild/linux-loong64@0.17.19: 145 | resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==} 146 | engines: {node: '>=12'} 147 | cpu: [loong64] 148 | os: [linux] 149 | requiresBuild: true 150 | dev: true 151 | optional: true 152 | 153 | /@esbuild/linux-mips64el@0.17.19: 154 | resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==} 155 | engines: {node: '>=12'} 156 | cpu: [mips64el] 157 | os: [linux] 158 | requiresBuild: true 159 | dev: true 160 | optional: true 161 | 162 | /@esbuild/linux-ppc64@0.17.19: 163 | resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==} 164 | engines: {node: '>=12'} 165 | cpu: [ppc64] 166 | os: [linux] 167 | requiresBuild: true 168 | dev: true 169 | optional: true 170 | 171 | /@esbuild/linux-riscv64@0.17.19: 172 | resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==} 173 | engines: {node: '>=12'} 174 | cpu: [riscv64] 175 | os: [linux] 176 | requiresBuild: true 177 | dev: true 178 | optional: true 179 | 180 | /@esbuild/linux-s390x@0.17.19: 181 | resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==} 182 | engines: {node: '>=12'} 183 | cpu: [s390x] 184 | os: [linux] 185 | requiresBuild: true 186 | dev: true 187 | optional: true 188 | 189 | /@esbuild/linux-x64@0.17.19: 190 | resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==} 191 | engines: {node: '>=12'} 192 | cpu: [x64] 193 | os: [linux] 194 | requiresBuild: true 195 | dev: true 196 | optional: true 197 | 198 | /@esbuild/netbsd-x64@0.17.19: 199 | resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==} 200 | engines: {node: '>=12'} 201 | cpu: [x64] 202 | os: [netbsd] 203 | requiresBuild: true 204 | dev: true 205 | optional: true 206 | 207 | /@esbuild/openbsd-x64@0.17.19: 208 | resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==} 209 | engines: {node: '>=12'} 210 | cpu: [x64] 211 | os: [openbsd] 212 | requiresBuild: true 213 | dev: true 214 | optional: true 215 | 216 | /@esbuild/sunos-x64@0.17.19: 217 | resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==} 218 | engines: {node: '>=12'} 219 | cpu: [x64] 220 | os: [sunos] 221 | requiresBuild: true 222 | dev: true 223 | optional: true 224 | 225 | /@esbuild/win32-arm64@0.17.19: 226 | resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==} 227 | engines: {node: '>=12'} 228 | cpu: [arm64] 229 | os: [win32] 230 | requiresBuild: true 231 | dev: true 232 | optional: true 233 | 234 | /@esbuild/win32-ia32@0.17.19: 235 | resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==} 236 | engines: {node: '>=12'} 237 | cpu: [ia32] 238 | os: [win32] 239 | requiresBuild: true 240 | dev: true 241 | optional: true 242 | 243 | /@esbuild/win32-x64@0.17.19: 244 | resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==} 245 | engines: {node: '>=12'} 246 | cpu: [x64] 247 | os: [win32] 248 | requiresBuild: true 249 | dev: true 250 | optional: true 251 | 252 | /@jridgewell/sourcemap-codec@1.4.15: 253 | resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} 254 | dev: true 255 | 256 | /@microsoft/api-extractor-model@7.27.0: 257 | resolution: {integrity: sha512-wHqIMiwSARmiuVLn/zmVpiRncq6hvBfC5GF+sjrN3w4FqVkqFYk7DetvfRNdy/3URdqqmYGrhJlcU9HpLnHOPg==} 258 | dependencies: 259 | '@microsoft/tsdoc': 0.14.2 260 | '@microsoft/tsdoc-config': 0.16.2 261 | '@rushstack/node-core-library': 3.59.1 262 | transitivePeerDependencies: 263 | - '@types/node' 264 | dev: true 265 | 266 | /@microsoft/api-extractor@7.35.0: 267 | resolution: {integrity: sha512-yBGfPJeEtzk8sg2hE2/vOPRvnJBvstbWNGeyGV1jIEUSgytzQ0QPgPEkOsP2n7nBfnyRXmZaBa2vJPGOzVWy+g==} 268 | hasBin: true 269 | dependencies: 270 | '@microsoft/api-extractor-model': 7.27.0 271 | '@microsoft/tsdoc': 0.14.2 272 | '@microsoft/tsdoc-config': 0.16.2 273 | '@rushstack/node-core-library': 3.59.1 274 | '@rushstack/rig-package': 0.3.19 275 | '@rushstack/ts-command-line': 4.13.3 276 | colors: 1.2.5 277 | lodash: 4.17.21 278 | resolve: 1.22.2 279 | semver: 7.3.8 280 | source-map: 0.6.1 281 | typescript: 5.0.4 282 | transitivePeerDependencies: 283 | - '@types/node' 284 | dev: true 285 | 286 | /@microsoft/tsdoc-config@0.16.2: 287 | resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==} 288 | dependencies: 289 | '@microsoft/tsdoc': 0.14.2 290 | ajv: 6.12.6 291 | jju: 1.4.0 292 | resolve: 1.19.0 293 | dev: true 294 | 295 | /@microsoft/tsdoc@0.14.2: 296 | resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==} 297 | dev: true 298 | 299 | /@nodelib/fs.scandir@2.1.5: 300 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} 301 | engines: {node: '>= 8'} 302 | dependencies: 303 | '@nodelib/fs.stat': 2.0.5 304 | run-parallel: 1.2.0 305 | dev: true 306 | 307 | /@nodelib/fs.stat@2.0.5: 308 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} 309 | engines: {node: '>= 8'} 310 | dev: true 311 | 312 | /@nodelib/fs.walk@1.2.8: 313 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 314 | engines: {node: '>= 8'} 315 | dependencies: 316 | '@nodelib/fs.scandir': 2.1.5 317 | fastq: 1.15.0 318 | dev: true 319 | 320 | /@petamoriken/float16@3.8.0: 321 | resolution: {integrity: sha512-AhVAm6SQ+zgxIiOzwVdUcDmKlu/qU39FiYD2UD6kQQaVenrn0dGZewIghWAENGQsvC+1avLCuT+T2/3Gsp/W3w==} 322 | dev: false 323 | 324 | /@rollup/pluginutils@5.0.2: 325 | resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} 326 | engines: {node: '>=14.0.0'} 327 | peerDependencies: 328 | rollup: ^1.20.0||^2.0.0||^3.0.0 329 | peerDependenciesMeta: 330 | rollup: 331 | optional: true 332 | dependencies: 333 | '@types/estree': 1.0.1 334 | estree-walker: 2.0.2 335 | picomatch: 2.3.1 336 | dev: true 337 | 338 | /@rushstack/node-core-library@3.59.1: 339 | resolution: {integrity: sha512-iy/xaEhXGpX+DY1ZzAtNA+QPw+9+TJh773Im+JxG4R1fu00/vWq470UOEj6upxlUxmp0JxhnmNRxzfptHrn/Uw==} 340 | peerDependencies: 341 | '@types/node': '*' 342 | peerDependenciesMeta: 343 | '@types/node': 344 | optional: true 345 | dependencies: 346 | colors: 1.2.5 347 | fs-extra: 7.0.1 348 | import-lazy: 4.0.0 349 | jju: 1.4.0 350 | resolve: 1.22.2 351 | semver: 7.3.8 352 | z-schema: 5.0.5 353 | dev: true 354 | 355 | /@rushstack/rig-package@0.3.19: 356 | resolution: {integrity: sha512-2d0/Gn+qjOYneZbiHjn4SjyDwq9I0WagV37z0F1V71G+yONgH7wlt3K/UoNiDkhA8gTHYPRo2jz3CvttybwSag==} 357 | dependencies: 358 | resolve: 1.22.2 359 | strip-json-comments: 3.1.1 360 | dev: true 361 | 362 | /@rushstack/ts-command-line@4.13.3: 363 | resolution: {integrity: sha512-6aQIv/o1EgsC/+SpgUyRmzg2QIAL6sudEzw3sWzJKwWuQTc5XRsyZpyldfE7WAmIqMXDao9QG35/NYORjHm5Zw==} 364 | dependencies: 365 | '@types/argparse': 1.0.38 366 | argparse: 1.0.10 367 | colors: 1.2.5 368 | string-argv: 0.3.2 369 | dev: true 370 | 371 | /@ts-morph/common@0.19.0: 372 | resolution: {integrity: sha512-Unz/WHmd4pGax91rdIKWi51wnVUW11QttMEPpBiBgIewnc9UQIX7UDLxr5vRlqeByXCwhkF6VabSsI0raWcyAQ==} 373 | dependencies: 374 | fast-glob: 3.2.12 375 | minimatch: 7.4.6 376 | mkdirp: 2.1.6 377 | path-browserify: 1.0.1 378 | dev: true 379 | 380 | /@types/argparse@1.0.38: 381 | resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} 382 | dev: true 383 | 384 | /@types/chai-subset@1.3.3: 385 | resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==} 386 | dependencies: 387 | '@types/chai': 4.3.5 388 | dev: true 389 | 390 | /@types/chai@4.3.5: 391 | resolution: {integrity: sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==} 392 | dev: true 393 | 394 | /@types/estree@1.0.1: 395 | resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==} 396 | dev: true 397 | 398 | /@types/node@20.2.3: 399 | resolution: {integrity: sha512-pg9d0yC4rVNWQzX8U7xb4olIOFuuVL9za3bzMT2pu2SU0SNEi66i2qrvhE2qt0HvkhuCaWJu7pLNOt/Pj8BIrw==} 400 | dev: true 401 | 402 | /@vitest/expect@0.31.1: 403 | resolution: {integrity: sha512-BV1LyNvhnX+eNYzJxlHIGPWZpwJFZaCcOIzp2CNG0P+bbetenTupk6EO0LANm4QFt0TTit+yqx7Rxd1qxi/SQA==} 404 | dependencies: 405 | '@vitest/spy': 0.31.1 406 | '@vitest/utils': 0.31.1 407 | chai: 4.3.7 408 | dev: true 409 | 410 | /@vitest/runner@0.31.1: 411 | resolution: {integrity: sha512-imWuc82ngOtxdCUpXwtEzZIuc1KMr+VlQ3Ondph45VhWoQWit5yvG/fFcldbnCi8DUuFi+NmNx5ehMUw/cGLUw==} 412 | dependencies: 413 | '@vitest/utils': 0.31.1 414 | concordance: 5.0.4 415 | p-limit: 4.0.0 416 | pathe: 1.1.0 417 | dev: true 418 | 419 | /@vitest/snapshot@0.31.1: 420 | resolution: {integrity: sha512-L3w5uU9bMe6asrNzJ8WZzN+jUTX4KSgCinEJPXyny0o90fG4FPQMV0OWsq7vrCWfQlAilMjDnOF9nP8lidsJ+g==} 421 | dependencies: 422 | magic-string: 0.30.0 423 | pathe: 1.1.0 424 | pretty-format: 27.5.1 425 | dev: true 426 | 427 | /@vitest/spy@0.31.1: 428 | resolution: {integrity: sha512-1cTpt2m9mdo3hRLDyCG2hDQvRrePTDgEJBFQQNz1ydHHZy03EiA6EpFxY+7ODaY7vMRCie+WlFZBZ0/dQWyssQ==} 429 | dependencies: 430 | tinyspy: 2.1.0 431 | dev: true 432 | 433 | /@vitest/utils@0.31.1: 434 | resolution: {integrity: sha512-yFyRD5ilwojsZfo3E0BnH72pSVSuLg2356cN1tCEe/0RtDzxTPYwOomIC+eQbot7m6DRy4tPZw+09mB7NkbMmA==} 435 | dependencies: 436 | concordance: 5.0.4 437 | loupe: 2.3.6 438 | pretty-format: 27.5.1 439 | dev: true 440 | 441 | /@webgpu/types@0.1.32: 442 | resolution: {integrity: sha512-H6JRAvRonWxqREjxXMZgQmdgIFPe6mykLgdrHY7EQE7YihMKd/SjtSGilUmMKECVdUMg2IQB9vzaXDiTj1AxZg==} 443 | dev: true 444 | 445 | /acorn-walk@8.2.0: 446 | resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} 447 | engines: {node: '>=0.4.0'} 448 | dev: true 449 | 450 | /acorn@8.8.2: 451 | resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} 452 | engines: {node: '>=0.4.0'} 453 | hasBin: true 454 | dev: true 455 | 456 | /ajv@6.12.6: 457 | resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} 458 | dependencies: 459 | fast-deep-equal: 3.1.3 460 | fast-json-stable-stringify: 2.1.0 461 | json-schema-traverse: 0.4.1 462 | uri-js: 4.4.1 463 | dev: true 464 | 465 | /ansi-regex@5.0.1: 466 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 467 | engines: {node: '>=8'} 468 | dev: true 469 | 470 | /ansi-styles@5.2.0: 471 | resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} 472 | engines: {node: '>=10'} 473 | dev: true 474 | 475 | /argparse@1.0.10: 476 | resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} 477 | dependencies: 478 | sprintf-js: 1.0.3 479 | dev: true 480 | 481 | /assertion-error@1.1.0: 482 | resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} 483 | dev: true 484 | 485 | /balanced-match@1.0.2: 486 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 487 | dev: true 488 | 489 | /blueimp-md5@2.19.0: 490 | resolution: {integrity: sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==} 491 | dev: true 492 | 493 | /brace-expansion@2.0.1: 494 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} 495 | dependencies: 496 | balanced-match: 1.0.2 497 | dev: true 498 | 499 | /braces@3.0.2: 500 | resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} 501 | engines: {node: '>=8'} 502 | dependencies: 503 | fill-range: 7.0.1 504 | dev: true 505 | 506 | /cac@6.7.14: 507 | resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} 508 | engines: {node: '>=8'} 509 | dev: true 510 | 511 | /chai@4.3.7: 512 | resolution: {integrity: sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==} 513 | engines: {node: '>=4'} 514 | dependencies: 515 | assertion-error: 1.1.0 516 | check-error: 1.0.2 517 | deep-eql: 4.1.3 518 | get-func-name: 2.0.0 519 | loupe: 2.3.6 520 | pathval: 1.1.1 521 | type-detect: 4.0.8 522 | dev: true 523 | 524 | /check-error@1.0.2: 525 | resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==} 526 | dev: true 527 | 528 | /code-block-writer@12.0.0: 529 | resolution: {integrity: sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w==} 530 | dev: true 531 | 532 | /colors@1.2.5: 533 | resolution: {integrity: sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg==} 534 | engines: {node: '>=0.1.90'} 535 | dev: true 536 | 537 | /commander@9.5.0: 538 | resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} 539 | engines: {node: ^12.20.0 || >=14} 540 | requiresBuild: true 541 | dev: true 542 | optional: true 543 | 544 | /concordance@5.0.4: 545 | resolution: {integrity: sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==} 546 | engines: {node: '>=10.18.0 <11 || >=12.14.0 <13 || >=14'} 547 | dependencies: 548 | date-time: 3.1.0 549 | esutils: 2.0.3 550 | fast-diff: 1.3.0 551 | js-string-escape: 1.0.1 552 | lodash: 4.17.21 553 | md5-hex: 3.0.1 554 | semver: 7.3.8 555 | well-known-symbols: 2.0.0 556 | dev: true 557 | 558 | /date-time@3.1.0: 559 | resolution: {integrity: sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==} 560 | engines: {node: '>=6'} 561 | dependencies: 562 | time-zone: 1.0.0 563 | dev: true 564 | 565 | /debug@4.3.4: 566 | resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} 567 | engines: {node: '>=6.0'} 568 | peerDependencies: 569 | supports-color: '*' 570 | peerDependenciesMeta: 571 | supports-color: 572 | optional: true 573 | dependencies: 574 | ms: 2.1.2 575 | dev: true 576 | 577 | /deep-eql@4.1.3: 578 | resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} 579 | engines: {node: '>=6'} 580 | dependencies: 581 | type-detect: 4.0.8 582 | dev: true 583 | 584 | /esbuild@0.17.19: 585 | resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==} 586 | engines: {node: '>=12'} 587 | hasBin: true 588 | requiresBuild: true 589 | optionalDependencies: 590 | '@esbuild/android-arm': 0.17.19 591 | '@esbuild/android-arm64': 0.17.19 592 | '@esbuild/android-x64': 0.17.19 593 | '@esbuild/darwin-arm64': 0.17.19 594 | '@esbuild/darwin-x64': 0.17.19 595 | '@esbuild/freebsd-arm64': 0.17.19 596 | '@esbuild/freebsd-x64': 0.17.19 597 | '@esbuild/linux-arm': 0.17.19 598 | '@esbuild/linux-arm64': 0.17.19 599 | '@esbuild/linux-ia32': 0.17.19 600 | '@esbuild/linux-loong64': 0.17.19 601 | '@esbuild/linux-mips64el': 0.17.19 602 | '@esbuild/linux-ppc64': 0.17.19 603 | '@esbuild/linux-riscv64': 0.17.19 604 | '@esbuild/linux-s390x': 0.17.19 605 | '@esbuild/linux-x64': 0.17.19 606 | '@esbuild/netbsd-x64': 0.17.19 607 | '@esbuild/openbsd-x64': 0.17.19 608 | '@esbuild/sunos-x64': 0.17.19 609 | '@esbuild/win32-arm64': 0.17.19 610 | '@esbuild/win32-ia32': 0.17.19 611 | '@esbuild/win32-x64': 0.17.19 612 | dev: true 613 | 614 | /estree-walker@2.0.2: 615 | resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} 616 | dev: true 617 | 618 | /esutils@2.0.3: 619 | resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} 620 | engines: {node: '>=0.10.0'} 621 | dev: true 622 | 623 | /fast-deep-equal@3.1.3: 624 | resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} 625 | dev: true 626 | 627 | /fast-diff@1.3.0: 628 | resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} 629 | dev: true 630 | 631 | /fast-glob@3.2.12: 632 | resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} 633 | engines: {node: '>=8.6.0'} 634 | dependencies: 635 | '@nodelib/fs.stat': 2.0.5 636 | '@nodelib/fs.walk': 1.2.8 637 | glob-parent: 5.1.2 638 | merge2: 1.4.1 639 | micromatch: 4.0.5 640 | dev: true 641 | 642 | /fast-json-stable-stringify@2.1.0: 643 | resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} 644 | dev: true 645 | 646 | /fastq@1.15.0: 647 | resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} 648 | dependencies: 649 | reusify: 1.0.4 650 | dev: true 651 | 652 | /fill-range@7.0.1: 653 | resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} 654 | engines: {node: '>=8'} 655 | dependencies: 656 | to-regex-range: 5.0.1 657 | dev: true 658 | 659 | /fs-extra@10.1.0: 660 | resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} 661 | engines: {node: '>=12'} 662 | dependencies: 663 | graceful-fs: 4.2.11 664 | jsonfile: 6.1.0 665 | universalify: 2.0.0 666 | dev: true 667 | 668 | /fs-extra@7.0.1: 669 | resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} 670 | engines: {node: '>=6 <7 || >=8'} 671 | dependencies: 672 | graceful-fs: 4.2.11 673 | jsonfile: 4.0.0 674 | universalify: 0.1.2 675 | dev: true 676 | 677 | /fsevents@2.3.2: 678 | resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} 679 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 680 | os: [darwin] 681 | requiresBuild: true 682 | dev: true 683 | optional: true 684 | 685 | /function-bind@1.1.1: 686 | resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} 687 | dev: true 688 | 689 | /get-func-name@2.0.0: 690 | resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==} 691 | dev: true 692 | 693 | /glob-parent@5.1.2: 694 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 695 | engines: {node: '>= 6'} 696 | dependencies: 697 | is-glob: 4.0.3 698 | dev: true 699 | 700 | /graceful-fs@4.2.11: 701 | resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} 702 | dev: true 703 | 704 | /has@1.0.3: 705 | resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} 706 | engines: {node: '>= 0.4.0'} 707 | dependencies: 708 | function-bind: 1.1.1 709 | dev: true 710 | 711 | /import-lazy@4.0.0: 712 | resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} 713 | engines: {node: '>=8'} 714 | dev: true 715 | 716 | /is-core-module@2.12.1: 717 | resolution: {integrity: sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==} 718 | dependencies: 719 | has: 1.0.3 720 | dev: true 721 | 722 | /is-extglob@2.1.1: 723 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 724 | engines: {node: '>=0.10.0'} 725 | dev: true 726 | 727 | /is-glob@4.0.3: 728 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 729 | engines: {node: '>=0.10.0'} 730 | dependencies: 731 | is-extglob: 2.1.1 732 | dev: true 733 | 734 | /is-number@7.0.0: 735 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 736 | engines: {node: '>=0.12.0'} 737 | dev: true 738 | 739 | /jju@1.4.0: 740 | resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} 741 | dev: true 742 | 743 | /js-string-escape@1.0.1: 744 | resolution: {integrity: sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==} 745 | engines: {node: '>= 0.8'} 746 | dev: true 747 | 748 | /json-schema-traverse@0.4.1: 749 | resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} 750 | dev: true 751 | 752 | /jsonc-parser@3.2.0: 753 | resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} 754 | dev: true 755 | 756 | /jsonfile@4.0.0: 757 | resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} 758 | optionalDependencies: 759 | graceful-fs: 4.2.11 760 | dev: true 761 | 762 | /jsonfile@6.1.0: 763 | resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} 764 | dependencies: 765 | universalify: 2.0.0 766 | optionalDependencies: 767 | graceful-fs: 4.2.11 768 | dev: true 769 | 770 | /kolorist@1.8.0: 771 | resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} 772 | dev: true 773 | 774 | /local-pkg@0.4.3: 775 | resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==} 776 | engines: {node: '>=14'} 777 | dev: true 778 | 779 | /lodash.get@4.4.2: 780 | resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} 781 | dev: true 782 | 783 | /lodash.isequal@4.5.0: 784 | resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} 785 | dev: true 786 | 787 | /lodash@4.17.21: 788 | resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} 789 | dev: true 790 | 791 | /loupe@2.3.6: 792 | resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==} 793 | dependencies: 794 | get-func-name: 2.0.0 795 | dev: true 796 | 797 | /lru-cache@6.0.0: 798 | resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} 799 | engines: {node: '>=10'} 800 | dependencies: 801 | yallist: 4.0.0 802 | dev: true 803 | 804 | /magic-string@0.29.0: 805 | resolution: {integrity: sha512-WcfidHrDjMY+eLjlU+8OvwREqHwpgCeKVBUpQ3OhYYuvfaYCUgcbuBzappNzZvg/v8onU3oQj+BYpkOJe9Iw4Q==} 806 | engines: {node: '>=12'} 807 | dependencies: 808 | '@jridgewell/sourcemap-codec': 1.4.15 809 | dev: true 810 | 811 | /magic-string@0.30.0: 812 | resolution: {integrity: sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==} 813 | engines: {node: '>=12'} 814 | dependencies: 815 | '@jridgewell/sourcemap-codec': 1.4.15 816 | dev: true 817 | 818 | /md5-hex@3.0.1: 819 | resolution: {integrity: sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==} 820 | engines: {node: '>=8'} 821 | dependencies: 822 | blueimp-md5: 2.19.0 823 | dev: true 824 | 825 | /merge2@1.4.1: 826 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 827 | engines: {node: '>= 8'} 828 | dev: true 829 | 830 | /micromatch@4.0.5: 831 | resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} 832 | engines: {node: '>=8.6'} 833 | dependencies: 834 | braces: 3.0.2 835 | picomatch: 2.3.1 836 | dev: true 837 | 838 | /minimatch@7.4.6: 839 | resolution: {integrity: sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==} 840 | engines: {node: '>=10'} 841 | dependencies: 842 | brace-expansion: 2.0.1 843 | dev: true 844 | 845 | /mkdirp@2.1.6: 846 | resolution: {integrity: sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==} 847 | engines: {node: '>=10'} 848 | hasBin: true 849 | dev: true 850 | 851 | /mlly@1.3.0: 852 | resolution: {integrity: sha512-HT5mcgIQKkOrZecOjOX3DJorTikWXwsBfpcr/MGBkhfWcjiqvnaL/9ppxvIUXfjT6xt4DVIAsN9fMUz1ev4bIw==} 853 | dependencies: 854 | acorn: 8.8.2 855 | pathe: 1.1.0 856 | pkg-types: 1.0.3 857 | ufo: 1.1.2 858 | dev: true 859 | 860 | /ms@2.1.2: 861 | resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} 862 | dev: true 863 | 864 | /nanoid@3.3.6: 865 | resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} 866 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 867 | hasBin: true 868 | dev: true 869 | 870 | /p-limit@4.0.0: 871 | resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} 872 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 873 | dependencies: 874 | yocto-queue: 1.0.0 875 | dev: true 876 | 877 | /path-browserify@1.0.1: 878 | resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} 879 | dev: true 880 | 881 | /path-parse@1.0.7: 882 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 883 | dev: true 884 | 885 | /pathe@1.1.0: 886 | resolution: {integrity: sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w==} 887 | dev: true 888 | 889 | /pathval@1.1.1: 890 | resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} 891 | dev: true 892 | 893 | /picocolors@1.0.0: 894 | resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} 895 | dev: true 896 | 897 | /picomatch@2.3.1: 898 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 899 | engines: {node: '>=8.6'} 900 | dev: true 901 | 902 | /pkg-types@1.0.3: 903 | resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==} 904 | dependencies: 905 | jsonc-parser: 3.2.0 906 | mlly: 1.3.0 907 | pathe: 1.1.0 908 | dev: true 909 | 910 | /postcss@8.4.23: 911 | resolution: {integrity: sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==} 912 | engines: {node: ^10 || ^12 || >=14} 913 | dependencies: 914 | nanoid: 3.3.6 915 | picocolors: 1.0.0 916 | source-map-js: 1.0.2 917 | dev: true 918 | 919 | /pretty-format@27.5.1: 920 | resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} 921 | engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} 922 | dependencies: 923 | ansi-regex: 5.0.1 924 | ansi-styles: 5.2.0 925 | react-is: 17.0.2 926 | dev: true 927 | 928 | /punycode@2.3.0: 929 | resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} 930 | engines: {node: '>=6'} 931 | dev: true 932 | 933 | /queue-microtask@1.2.3: 934 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 935 | dev: true 936 | 937 | /react-is@17.0.2: 938 | resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} 939 | dev: true 940 | 941 | /resolve@1.19.0: 942 | resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==} 943 | dependencies: 944 | is-core-module: 2.12.1 945 | path-parse: 1.0.7 946 | dev: true 947 | 948 | /resolve@1.22.2: 949 | resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==} 950 | hasBin: true 951 | dependencies: 952 | is-core-module: 2.12.1 953 | path-parse: 1.0.7 954 | supports-preserve-symlinks-flag: 1.0.0 955 | dev: true 956 | 957 | /reusify@1.0.4: 958 | resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} 959 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 960 | dev: true 961 | 962 | /rollup@3.23.0: 963 | resolution: {integrity: sha512-h31UlwEi7FHihLe1zbk+3Q7z1k/84rb9BSwmBSr/XjOCEaBJ2YyedQDuM0t/kfOS0IxM+vk1/zI9XxYj9V+NJQ==} 964 | engines: {node: '>=14.18.0', npm: '>=8.0.0'} 965 | hasBin: true 966 | optionalDependencies: 967 | fsevents: 2.3.2 968 | dev: true 969 | 970 | /run-parallel@1.2.0: 971 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 972 | dependencies: 973 | queue-microtask: 1.2.3 974 | dev: true 975 | 976 | /semver@7.3.8: 977 | resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} 978 | engines: {node: '>=10'} 979 | hasBin: true 980 | dependencies: 981 | lru-cache: 6.0.0 982 | dev: true 983 | 984 | /siginfo@2.0.0: 985 | resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} 986 | dev: true 987 | 988 | /source-map-js@1.0.2: 989 | resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} 990 | engines: {node: '>=0.10.0'} 991 | dev: true 992 | 993 | /source-map@0.6.1: 994 | resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} 995 | engines: {node: '>=0.10.0'} 996 | dev: true 997 | 998 | /sprintf-js@1.0.3: 999 | resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} 1000 | dev: true 1001 | 1002 | /stackback@0.0.2: 1003 | resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} 1004 | dev: true 1005 | 1006 | /std-env@3.3.3: 1007 | resolution: {integrity: sha512-Rz6yejtVyWnVjC1RFvNmYL10kgjC49EOghxWn0RFqlCHGFpQx+Xe7yW3I4ceK1SGrWIGMjD5Kbue8W/udkbMJg==} 1008 | dev: true 1009 | 1010 | /string-argv@0.3.2: 1011 | resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} 1012 | engines: {node: '>=0.6.19'} 1013 | dev: true 1014 | 1015 | /strip-json-comments@3.1.1: 1016 | resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} 1017 | engines: {node: '>=8'} 1018 | dev: true 1019 | 1020 | /strip-literal@1.0.1: 1021 | resolution: {integrity: sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q==} 1022 | dependencies: 1023 | acorn: 8.8.2 1024 | dev: true 1025 | 1026 | /supports-preserve-symlinks-flag@1.0.0: 1027 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 1028 | engines: {node: '>= 0.4'} 1029 | dev: true 1030 | 1031 | /time-zone@1.0.0: 1032 | resolution: {integrity: sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==} 1033 | engines: {node: '>=4'} 1034 | dev: true 1035 | 1036 | /tinybench@2.5.0: 1037 | resolution: {integrity: sha512-kRwSG8Zx4tjF9ZiyH4bhaebu+EDz1BOx9hOigYHlUW4xxI/wKIUQUqo018UlU4ar6ATPBsaMrdbKZ+tmPdohFA==} 1038 | dev: true 1039 | 1040 | /tinypool@0.5.0: 1041 | resolution: {integrity: sha512-paHQtnrlS1QZYKF/GnLoOM/DN9fqaGOFbCbxzAhwniySnzl9Ebk8w73/dd34DAhe/obUbPAOldTyYXQZxnPBPQ==} 1042 | engines: {node: '>=14.0.0'} 1043 | dev: true 1044 | 1045 | /tinyspy@2.1.0: 1046 | resolution: {integrity: sha512-7eORpyqImoOvkQJCSkL0d0mB4NHHIFAy4b1u8PHdDa7SjGS2njzl6/lyGoZLm+eyYEtlUmFGE0rFj66SWxZgQQ==} 1047 | engines: {node: '>=14.0.0'} 1048 | dev: true 1049 | 1050 | /to-fast-properties@2.0.0: 1051 | resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} 1052 | engines: {node: '>=4'} 1053 | dev: true 1054 | 1055 | /to-regex-range@5.0.1: 1056 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 1057 | engines: {node: '>=8.0'} 1058 | dependencies: 1059 | is-number: 7.0.0 1060 | dev: true 1061 | 1062 | /ts-morph@18.0.0: 1063 | resolution: {integrity: sha512-Kg5u0mk19PIIe4islUI/HWRvm9bC1lHejK4S0oh1zaZ77TMZAEmQC0sHQYiu2RgCQFZKXz1fMVi/7nOOeirznA==} 1064 | dependencies: 1065 | '@ts-morph/common': 0.19.0 1066 | code-block-writer: 12.0.0 1067 | dev: true 1068 | 1069 | /type-detect@4.0.8: 1070 | resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} 1071 | engines: {node: '>=4'} 1072 | dev: true 1073 | 1074 | /typescript@5.0.2: 1075 | resolution: {integrity: sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==} 1076 | engines: {node: '>=12.20'} 1077 | hasBin: true 1078 | dev: true 1079 | 1080 | /typescript@5.0.4: 1081 | resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==} 1082 | engines: {node: '>=12.20'} 1083 | hasBin: true 1084 | dev: true 1085 | 1086 | /ufo@1.1.2: 1087 | resolution: {integrity: sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ==} 1088 | dev: true 1089 | 1090 | /universalify@0.1.2: 1091 | resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} 1092 | engines: {node: '>= 4.0.0'} 1093 | dev: true 1094 | 1095 | /universalify@2.0.0: 1096 | resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} 1097 | engines: {node: '>= 10.0.0'} 1098 | dev: true 1099 | 1100 | /uri-js@4.4.1: 1101 | resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} 1102 | dependencies: 1103 | punycode: 2.3.0 1104 | dev: true 1105 | 1106 | /validator@13.9.0: 1107 | resolution: {integrity: sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA==} 1108 | engines: {node: '>= 0.10'} 1109 | dev: true 1110 | 1111 | /vite-node@0.31.1(@types/node@20.2.3): 1112 | resolution: {integrity: sha512-BajE/IsNQ6JyizPzu9zRgHrBwczkAs0erQf/JRpgTIESpKvNj9/Gd0vxX905klLkb0I0SJVCKbdrl5c6FnqYKA==} 1113 | engines: {node: '>=v14.18.0'} 1114 | hasBin: true 1115 | dependencies: 1116 | cac: 6.7.14 1117 | debug: 4.3.4 1118 | mlly: 1.3.0 1119 | pathe: 1.1.0 1120 | picocolors: 1.0.0 1121 | vite: 4.3.2(@types/node@20.2.3) 1122 | transitivePeerDependencies: 1123 | - '@types/node' 1124 | - less 1125 | - sass 1126 | - stylus 1127 | - sugarss 1128 | - supports-color 1129 | - terser 1130 | dev: true 1131 | 1132 | /vite-plugin-dts@2.3.0(vite@4.3.2): 1133 | resolution: {integrity: sha512-WbJgGtsStgQhdm3EosYmIdTGbag5YQpZ3HXWUAPCDyoXI5qN6EY0V7NXq0lAmnv9hVQsvh0htbYcg0Or5Db9JQ==} 1134 | engines: {node: ^14.18.0 || >=16.0.0} 1135 | peerDependencies: 1136 | vite: '>=2.9.0' 1137 | dependencies: 1138 | '@babel/parser': 7.21.9 1139 | '@microsoft/api-extractor': 7.35.0 1140 | '@rollup/pluginutils': 5.0.2 1141 | '@rushstack/node-core-library': 3.59.1 1142 | debug: 4.3.4 1143 | fast-glob: 3.2.12 1144 | fs-extra: 10.1.0 1145 | kolorist: 1.8.0 1146 | magic-string: 0.29.0 1147 | ts-morph: 18.0.0 1148 | vite: 4.3.2(@types/node@20.2.3) 1149 | transitivePeerDependencies: 1150 | - '@types/node' 1151 | - rollup 1152 | - supports-color 1153 | dev: true 1154 | 1155 | /vite@4.3.2(@types/node@20.2.3): 1156 | resolution: {integrity: sha512-9R53Mf+TBoXCYejcL+qFbZde+eZveQLDYd9XgULILLC1a5ZwPaqgmdVpL8/uvw2BM/1TzetWjglwm+3RO+xTyw==} 1157 | engines: {node: ^14.18.0 || >=16.0.0} 1158 | hasBin: true 1159 | peerDependencies: 1160 | '@types/node': '>= 14' 1161 | less: '*' 1162 | sass: '*' 1163 | stylus: '*' 1164 | sugarss: '*' 1165 | terser: ^5.4.0 1166 | peerDependenciesMeta: 1167 | '@types/node': 1168 | optional: true 1169 | less: 1170 | optional: true 1171 | sass: 1172 | optional: true 1173 | stylus: 1174 | optional: true 1175 | sugarss: 1176 | optional: true 1177 | terser: 1178 | optional: true 1179 | dependencies: 1180 | '@types/node': 20.2.3 1181 | esbuild: 0.17.19 1182 | postcss: 8.4.23 1183 | rollup: 3.23.0 1184 | optionalDependencies: 1185 | fsevents: 2.3.2 1186 | dev: true 1187 | 1188 | /vitest@0.31.1: 1189 | resolution: {integrity: sha512-/dOoOgzoFk/5pTvg1E65WVaobknWREN15+HF+0ucudo3dDG/vCZoXTQrjIfEaWvQXmqScwkRodrTbM/ScMpRcQ==} 1190 | engines: {node: '>=v14.18.0'} 1191 | hasBin: true 1192 | peerDependencies: 1193 | '@edge-runtime/vm': '*' 1194 | '@vitest/browser': '*' 1195 | '@vitest/ui': '*' 1196 | happy-dom: '*' 1197 | jsdom: '*' 1198 | playwright: '*' 1199 | safaridriver: '*' 1200 | webdriverio: '*' 1201 | peerDependenciesMeta: 1202 | '@edge-runtime/vm': 1203 | optional: true 1204 | '@vitest/browser': 1205 | optional: true 1206 | '@vitest/ui': 1207 | optional: true 1208 | happy-dom: 1209 | optional: true 1210 | jsdom: 1211 | optional: true 1212 | playwright: 1213 | optional: true 1214 | safaridriver: 1215 | optional: true 1216 | webdriverio: 1217 | optional: true 1218 | dependencies: 1219 | '@types/chai': 4.3.5 1220 | '@types/chai-subset': 1.3.3 1221 | '@types/node': 20.2.3 1222 | '@vitest/expect': 0.31.1 1223 | '@vitest/runner': 0.31.1 1224 | '@vitest/snapshot': 0.31.1 1225 | '@vitest/spy': 0.31.1 1226 | '@vitest/utils': 0.31.1 1227 | acorn: 8.8.2 1228 | acorn-walk: 8.2.0 1229 | cac: 6.7.14 1230 | chai: 4.3.7 1231 | concordance: 5.0.4 1232 | debug: 4.3.4 1233 | local-pkg: 0.4.3 1234 | magic-string: 0.30.0 1235 | pathe: 1.1.0 1236 | picocolors: 1.0.0 1237 | std-env: 3.3.3 1238 | strip-literal: 1.0.1 1239 | tinybench: 2.5.0 1240 | tinypool: 0.5.0 1241 | vite: 4.3.2(@types/node@20.2.3) 1242 | vite-node: 0.31.1(@types/node@20.2.3) 1243 | why-is-node-running: 2.2.2 1244 | transitivePeerDependencies: 1245 | - less 1246 | - sass 1247 | - stylus 1248 | - sugarss 1249 | - supports-color 1250 | - terser 1251 | dev: true 1252 | 1253 | /well-known-symbols@2.0.0: 1254 | resolution: {integrity: sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==} 1255 | engines: {node: '>=6'} 1256 | dev: true 1257 | 1258 | /why-is-node-running@2.2.2: 1259 | resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==} 1260 | engines: {node: '>=8'} 1261 | hasBin: true 1262 | dependencies: 1263 | siginfo: 2.0.0 1264 | stackback: 0.0.2 1265 | dev: true 1266 | 1267 | /yallist@4.0.0: 1268 | resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} 1269 | dev: true 1270 | 1271 | /yocto-queue@1.0.0: 1272 | resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} 1273 | engines: {node: '>=12.20'} 1274 | dev: true 1275 | 1276 | /z-schema@5.0.5: 1277 | resolution: {integrity: sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==} 1278 | engines: {node: '>=8.0.0'} 1279 | hasBin: true 1280 | dependencies: 1281 | lodash.get: 4.4.2 1282 | lodash.isequal: 4.5.0 1283 | validator: 13.9.0 1284 | optionalDependencies: 1285 | commander: 9.5.0 1286 | dev: true 1287 | -------------------------------------------------------------------------------- /src/StructBuffer.test.ts: -------------------------------------------------------------------------------- 1 | import { wgsl, setPolyfill } from './index'; 2 | import { expect, test } from 'vitest'; 3 | import * as polyfill from '@petamoriken/float16'; 4 | 5 | setPolyfill(polyfill); 6 | 7 | test('StructBuffer simple', () => { 8 | const struct = new wgsl.StructBuffer({ 9 | ambient: 'vec3f', 10 | lightCount: 'u32', 11 | lights: [ 12 | { 13 | position: 'vec3f', 14 | range: 'f32', 15 | color: 'vec3f', 16 | intensity: 'f32', 17 | }, 18 | 4, 19 | ], 20 | }); 21 | 22 | let i = 0; 23 | struct.view.ambient.set([++i, ++i, ++i]); 24 | struct.view.lightCount = ++i; 25 | struct.view.lights.forEach(light => { 26 | light.color.set([++i, ++i, ++i]); 27 | light.position.set([++i, ++i, ++i]); 28 | light.intensity = ++i; 29 | light.range = ++i; 30 | }); 31 | 32 | // console.log(struct.view); 33 | // console.log(struct.buffer); 34 | 35 | i = 0; 36 | expect(struct.view.ambient).toStrictEqual(new Float32Array([++i, ++i, ++i])); 37 | expect(struct.view.lightCount).toStrictEqual(++i); 38 | struct.view.lights.forEach(light => { 39 | expect(light.color).toStrictEqual(new Float32Array([++i, ++i, ++i])); 40 | expect(light.position).toStrictEqual(new Float32Array([++i, ++i, ++i])); 41 | expect(light.intensity).toStrictEqual(++i); 42 | expect(light.range).toStrictEqual(++i); 43 | 44 | expect(() => (light.color = new Float32Array())).toThrowError(); 45 | }); 46 | 47 | expect(() => (struct.view.lights[2] = {} as any)).toThrowError(); 48 | expect(() => (struct.view.lights[4] = {} as any)).toThrowError(); 49 | }); 50 | 51 | test('StructBuffer view', () => { 52 | const substruct = { 53 | vec2_0: 'vec2f', 54 | vec2_1: 'vec2f', 55 | subarray: [ 56 | { 57 | f32_: 'f32', 58 | i32_: 'i32', 59 | }, 60 | 2, 61 | ], 62 | } satisfies wgsl.Struct; 63 | const { view, info } = new wgsl.StructBuffer( 64 | { 65 | u32_: 'u32', 66 | i32_: 'i32', 67 | f32_: 'f32', 68 | f16_: 'f16', 69 | 70 | vec2_: 'vec2f', 71 | vec2i_: 'vec2i', 72 | vec2u_: 'vec2u', 73 | vec2h_: 'vec2h', 74 | 75 | vec3_: 'vec3f', 76 | vec3i_: 'vec3i', 77 | vec3u_: 'vec3u', 78 | vec3h_: 'vec3h', 79 | 80 | vec4_: 'vec4f', 81 | vec4h_: 'vec4h', 82 | vec4i_: 'vec4i', 83 | vec4u_: 'vec4u', 84 | 85 | mat3_: 'mat3x3f', 86 | mat4_: 'mat4x4f', 87 | mat3h_: 'mat3x3h', 88 | mat4h_: 'mat4x4h', 89 | 90 | substruct: substruct, 91 | subarray: [substruct, 2], 92 | }, 93 | false, 94 | true, 95 | ); 96 | view.f32_ = 1; 97 | view.i32_ = 2; 98 | view.u32_ = -1; 99 | view.f16_ = 3.140624; 100 | view.vec2h_.set([0.5, 0.000030517578124]); // 注意最后一位 101 | view.vec3h_.set([3.140625, 3.140625]); 102 | view.vec4h_.set([3.140625, 3.140625]); 103 | console.log(info); 104 | expect(view.f32_).toBe(1); 105 | expect(view.i32_).toBe(2); 106 | expect(view.u32_).toBe(4294967295); 107 | expect(view.f16_).toBe(3.138671875); 108 | expect([...view.vec2h_]).toStrictEqual([0.5, 0.000030517578125]); 109 | 110 | expect(view.vec2_.length).toBe(2); 111 | expect(view.vec2_.byteOffset).toBe(info!.vec2_.offset); 112 | expect(view.vec3_.length).toBe(3); 113 | expect(view.vec3_.byteOffset).toBe(info!.vec3_.offset); 114 | expect(view.vec4_.length).toBe(4); 115 | expect(view.vec4_.byteOffset).toBe(info!.vec4_.offset); 116 | expect(view.mat3_.length).toBe(12); 117 | expect(view.mat3_.byteOffset).toBe(info!.mat3_.offset); 118 | expect(view.mat4_.length).toBe(16); 119 | expect(view.mat4_.byteOffset).toBe(info!.mat4_.offset); 120 | expect(view.substruct.subarray.length).toBe(2); 121 | expect(view.subarray.length).toBe(2); 122 | expect(view.subarray[0].subarray.length).toBe(2); 123 | }); 124 | 125 | test('StructBuffer ignore align', () => { 126 | const { view } = new wgsl.StructBuffer( 127 | { 128 | a: 'vec2f', 129 | b: 'vec3f', 130 | c: 'vec4f', 131 | d: 'f32', 132 | e: 'mat3x3f', 133 | f: 'mat4x4f', 134 | }, 135 | true, 136 | ); 137 | 138 | expect(view.a.byteOffset).toBe(0); 139 | expect(view.b.byteOffset).toBe(4 * 2); 140 | expect(view.c.byteOffset).toBe(4 * 5); 141 | expect(view.e.byteOffset).toBe(4 * 10); 142 | expect(view.f.byteOffset).toBe(4 * 22); 143 | }); 144 | 145 | test('StructBuffer stringifyStruct', () => { 146 | const substruct = wgsl.struct({ 147 | vec2_0: 'vec2f', 148 | vec2_1: 'vec2f', 149 | subarray: [ 150 | { 151 | f32_: 'f32', 152 | i32_: 'i32', 153 | }, 154 | 2, 155 | ], 156 | }); 157 | const str = wgsl.stringifyStruct('Test', { 158 | u32_: 'u32', 159 | i32_: 'i32', 160 | f32_: 'f32', 161 | vec2_: 'vec2f', 162 | vec3_: 'vec3f', 163 | vec4_: 'vec4f', 164 | mat3_: 'mat3x3f', 165 | mat4_: 'mat4x4f', 166 | substruct, 167 | subarray: [substruct, 2], 168 | }); 169 | console.log(str); 170 | expect(str).toBe(`struct Test_substruct_subarray { 171 | f32_: f32, 172 | i32_: i32, 173 | }; 174 | struct Test_substruct { 175 | vec2_0: vec2f, 176 | vec2_1: vec2f, 177 | subarray: array, 178 | }; 179 | struct Test { 180 | u32_: u32, 181 | i32_: i32, 182 | f32_: f32, 183 | vec2_: vec2f, 184 | vec3_: vec3f, 185 | vec4_: vec4f, 186 | mat3_: mat3x3f, 187 | mat4_: mat4x4f, 188 | substruct: Test_substruct, 189 | subarray: array, 190 | };`); 191 | }); 192 | -------------------------------------------------------------------------------- /src/StructBuffer.ts: -------------------------------------------------------------------------------- 1 | import type { Float16Array, Float16ArrayConstructor } from '@petamoriken/float16'; 2 | 3 | type NoEmptyRecord = T & (keyof T extends never ? 'No empty object' : {}); 4 | 5 | enum PrimitiveDataViewGet { 6 | f16 = 'getFloat16', 7 | f32 = 'getFloat32', 8 | u32 = 'getUint32', 9 | i32 = 'getInt32', 10 | } 11 | 12 | enum PrimitiveDataViewSet { 13 | f16 = 'setFloat16', 14 | f32 = 'setFloat32', 15 | u32 = 'setUint32', 16 | i32 = 'setInt32', 17 | } 18 | 19 | export namespace wgsl { 20 | export enum PrimitiveToGPUVertexFormat { 21 | u32 = 'uint32', 22 | i32 = 'sint32', 23 | f32 = 'float32', 24 | vec2f = 'float32x2', 25 | vec3f = 'float32x3', 26 | vec4f = 'float32x4', 27 | vec2h = 'float16x2', 28 | vec4h = 'float16x4', 29 | vec2i = 'sint32x2', 30 | vec3i = 'sint32x3', 31 | vec4i = 'sint32x4', 32 | vec2u = 'uint32x2', 33 | vec3u = 'uint32x3', 34 | vec4u = 'uint32x4', 35 | } 36 | 37 | const PrimitiveTypedArrayLenMap = Object.freeze({ 38 | vec2: 2, 39 | vec3: 3, 40 | vec4: 4, // mat3x3 layout: 1 1 1 0 41 | mat3x3: 12, // = 48 / 4 1 1 1 0 42 | mat4x4: 16, // 1 1 1 0 43 | } as const); 44 | 45 | const PrimitiveAlignSize: { [K in Primitive]: { size: number; align: number } } = Object.freeze({ 46 | f16: { size: 2, align: 2 }, 47 | f32: { size: 4, align: 4 }, 48 | u32: { size: 4, align: 4 }, 49 | i32: { size: 4, align: 4 }, 50 | 51 | vec2f: { size: 8, align: 8 }, 52 | vec2u: { size: 8, align: 8 }, 53 | vec2i: { size: 8, align: 8 }, 54 | 55 | vec3f: { size: 12, align: 16 }, 56 | vec3u: { size: 12, align: 16 }, 57 | vec3i: { size: 12, align: 16 }, 58 | 59 | vec4f: { size: 16, align: 16 }, 60 | vec4u: { size: 16, align: 16 }, 61 | vec4i: { size: 16, align: 16 }, 62 | 63 | mat3x3f: { size: 48, align: 16 }, 64 | mat4x4f: { size: 64, align: 16 }, 65 | 66 | vec2h: { size: 4, align: 4 }, 67 | vec3h: { size: 6, align: 8 }, 68 | vec4h: { size: 8, align: 8 }, 69 | mat3x3h: { size: 24, align: 8 }, 70 | mat4x4h: { size: 32, align: 8 }, 71 | }); 72 | 73 | export const SuffixTypedArrayMap = { 74 | h: undefined as unknown as Float16ArrayConstructor, 75 | f: Float32Array, 76 | u: Uint32Array, 77 | i: Int32Array, 78 | } as const; 79 | 80 | export type PrimitiveNumber = 'f16' | 'f32' | 'u32' | 'i32'; 81 | export type PrimitiveVector = `${'vec2' | 'vec3' | 'vec4'}${'f' | 'h' | 'u' | 'i'}`; 82 | export type PrimitiveMatrix = `${'mat3x3' | 'mat4x4'}${'f' | 'h'}`; 83 | export type PrimitiveTypedArray = PrimitiveVector | PrimitiveMatrix; 84 | export type Primitive = PrimitiveNumber | PrimitiveTypedArray; 85 | export type PrimitiveView = { 86 | f16: number; 87 | f32: number; 88 | u32: number; 89 | i32: number; 90 | vec2f: Float32Array; 91 | vec2u: Uint32Array; 92 | vec2i: Int32Array; 93 | vec3f: Float32Array; 94 | vec3u: Uint32Array; 95 | vec3i: Int32Array; 96 | vec4f: Float32Array; 97 | vec4u: Uint32Array; 98 | vec4i: Int32Array; 99 | mat4x4f: Float32Array; 100 | mat3x3f: Float32Array; 101 | vec2h: Float16Array; 102 | vec3h: Float16Array; 103 | vec4h: Float16Array; 104 | mat4x4h: Float16Array; 105 | mat3x3h: Float16Array; 106 | }; 107 | export type Array = [struct: Struct, length: number, runtimeSized?: boolean]; 108 | export type Struct = { [k: string]: Primitive | Array | Struct }; 109 | export type PlainStruct = { [k: string]: Exclude }; 110 | export type StructView = { 111 | [K in keyof T]: T[K] extends Struct 112 | ? StructView 113 | : T[K] extends Array 114 | ? StructView[] 115 | : T[K] extends Primitive 116 | ? PrimitiveView[T[K]] 117 | : never; 118 | }; 119 | export type StructInfo = { 120 | [K in keyof T]: T[K] extends Struct 121 | ? StructInfo 122 | : T[K] extends Array 123 | ? StructInfo[] 124 | : T[K] extends Primitive 125 | ? { offset: number; size: number } 126 | : never; 127 | }; 128 | 129 | export type PlainStructInfo = { 130 | [K in keyof T]: { size: number; offset: number }; 131 | }; 132 | 133 | function nextAlign(current: number, align: number): number { 134 | let aligned = current - (current % align); 135 | if (current % align != 0) aligned += align; 136 | return aligned; 137 | } 138 | 139 | export function structSize(struct: T, ignoreAlign?: boolean): number { 140 | let stride = 0; 141 | for (const value of Object.values(struct)) { 142 | const { align, size } = structValueSizeAlign(value); 143 | stride = nextAlign(stride, ignoreAlign ? 1 : align) + size; 144 | } 145 | stride = nextAlign(stride, structAlign(struct, ignoreAlign)); 146 | return stride; 147 | } 148 | 149 | function structValueSizeAlign(value: Primitive | Array | Struct) { 150 | let align: number, size: number, itemSize: number | undefined; 151 | if (Array.isArray(value)) { 152 | align = structAlign(value[0]); 153 | itemSize = structSize(value[0]); 154 | size = itemSize * value[1]; 155 | } else if (typeof value === 'object') { 156 | align = structAlign(value); 157 | size = structSize(value); 158 | } else { 159 | ({ align, size } = PrimitiveAlignSize[value]); 160 | } 161 | return { align, size, itemSize: itemSize ?? size }; 162 | } 163 | 164 | export function structAlign(struct: T, ignoreAlign?: boolean): number { 165 | if (ignoreAlign) return 1; 166 | return Math.max( 167 | ...Object.values(struct).map(value => { 168 | if (Array.isArray(value)) return structAlign(value[0]); 169 | else if (typeof value === 'object') return structAlign(value); 170 | else return PrimitiveAlignSize[value].align; 171 | }), 172 | ); 173 | } 174 | 175 | export function structView( 176 | buffer: ArrayBuffer, 177 | struct: T, 178 | byteOffset = 0, 179 | ignoreAlign = false, 180 | info?: any, 181 | ): StructView { 182 | const view: any = {}; 183 | const dataView = new DataView(buffer); 184 | let stride = byteOffset; 185 | 186 | for (let [key, value] of Object.entries(struct)) { 187 | const { align, size, itemSize } = structValueSizeAlign(value); 188 | const offset = nextAlign(stride, ignoreAlign ? 1 : align); 189 | 190 | if (Array.isArray(value)) { 191 | const arrayView: any[] = new Array(value[1]); 192 | if (info) { 193 | const arrayInfo = []; 194 | for (let i = 0, il = value[1]; i < il; i++) { 195 | arrayInfo[i] = {}; 196 | arrayView[i] = structView( 197 | buffer, 198 | value[0], 199 | offset + itemSize * i, 200 | ignoreAlign, 201 | arrayInfo[i], 202 | ); 203 | } 204 | info[key] = arrayInfo; 205 | } else 206 | for (let i = 0, il = value[1]; i < il; i++) { 207 | arrayView[i] = structView(buffer, value[0], offset + itemSize * i, ignoreAlign); 208 | } 209 | Object.freeze(arrayView); 210 | view[key] = arrayView; 211 | } else if (typeof value === 'object') { 212 | if (info) info[key] = {}; 213 | view[key] = structView(buffer, value, offset, ignoreAlign, info ? info[key] : undefined); 214 | } else { 215 | if (info) info[key] = { offset, size }; 216 | if (value.startsWith('vec') || value.startsWith('mat')) { 217 | const suffixType = value[value.length - 1] as 'h' | 'f' | 'i' | 'u'; 218 | const prefix = value.slice(0, -1) as `vec${'2' | '3' | '4'}` | `mat${'3x3' | '4x4'}`; 219 | const TypedArray = SuffixTypedArrayMap[suffixType]; 220 | const length = PrimitiveTypedArrayLenMap[prefix]; 221 | view[key] = new TypedArray(buffer, offset, length); 222 | } else { 223 | const numberValue = value as PrimitiveNumber; 224 | const get = PrimitiveDataViewGet[numberValue]; 225 | const set = PrimitiveDataViewSet[numberValue]; 226 | Object.defineProperty(view, key, { 227 | get(): number { 228 | return dataView[get](offset, true); 229 | }, 230 | set(v: number) { 231 | dataView[set](offset, v, true); 232 | }, 233 | }); 234 | } 235 | } 236 | 237 | stride = offset + size; 238 | } 239 | Object.freeze(view); 240 | return view as StructView; 241 | } 242 | 243 | export function plainStructInfo( 244 | plainStruct: T, 245 | ignoreAlign?: boolean, 246 | ): PlainStructInfo { 247 | const info: any = {}; 248 | let stride = 0; 249 | for (let [key, value] of Object.entries(plainStruct)) { 250 | const { align, size } = structValueSizeAlign(value); 251 | const offset = nextAlign(stride, ignoreAlign ? 1 : align); 252 | info[key] = { offset, size }; 253 | stride = offset + size; 254 | } 255 | return info; 256 | } 257 | 258 | // 更推荐使用 {} satisfies wgsl.Struct 259 | export function struct(struct: T) { 260 | return struct; 261 | } 262 | 263 | export class StructBuffer { 264 | buffer: Uint8Array; 265 | view: StructView>; 266 | info?: StructInfo>; 267 | constructor(public struct: NoEmptyRecord, ignoreAlign?: boolean, genInfo?: boolean) { 268 | const byteLength = wgsl.structSize(struct, ignoreAlign); 269 | this.buffer = new Uint8Array(byteLength); 270 | if (genInfo) this.info = {} as StructInfo>; 271 | this.view = wgsl.structView(this.buffer.buffer, struct, 0, ignoreAlign, this.info); 272 | } 273 | 274 | clone() { 275 | return new StructBuffer(this.struct); 276 | } 277 | } 278 | 279 | export function stringifyStruct( 280 | name: string, 281 | struct: NoEmptyRecord, 282 | structCache = new Map(), 283 | ) { 284 | let structStr = `struct ${name} { 285 | ${Object.entries(struct) 286 | .map(([key, value]) => { 287 | let typeStr: string; 288 | if (Array.isArray(value)) { 289 | typeStr = `array<${name}_${key}${value[2] ? '' : `, ${value[1]}`}>`; 290 | if (!structCache.has(JSON.stringify(value[0]))) { 291 | stringifyStruct(`${name}_${key}`, value[0], structCache); 292 | } 293 | } else if (typeof value === 'object') { 294 | typeStr = `${name}_${key}`; 295 | if (!structCache.has(JSON.stringify(value))) { 296 | stringifyStruct(typeStr, value, structCache); 297 | } 298 | } else { 299 | typeStr = value; 300 | } 301 | return ` ${key}: ${typeStr},`; 302 | }) 303 | .join('\n')} 304 | };`; 305 | structCache.set(JSON.stringify(struct), { name, structStr }); 306 | const subStruct = [...structCache.values()] 307 | .filter(i => i.name !== name) 308 | .map(i => i.structStr) 309 | .join('\n'); 310 | return subStruct + '\n' + structStr; 311 | } 312 | } 313 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './StructBuffer'; 2 | export * from './polyfill'; 3 | -------------------------------------------------------------------------------- /src/polyfill.ts: -------------------------------------------------------------------------------- 1 | import type { Float16ArrayConstructor } from '@petamoriken/float16'; 2 | import { wgsl } from './StructBuffer'; 3 | 4 | declare global { 5 | interface DataView { 6 | getFloat16(byteOffset: number, littleEndian?: boolean): number; 7 | setFloat16(byteOffset: number, value: number, littleEndian?: boolean): void; 8 | } 9 | } 10 | 11 | export function setPolyfill(polyfill: { 12 | getFloat16: any; 13 | setFloat16: any; 14 | Float16Array: Float16ArrayConstructor; 15 | }) { 16 | const { getFloat16, setFloat16, Float16Array } = polyfill; 17 | DataView.prototype.getFloat16 = function (byteOffset: number, littleEndian?: boolean) { 18 | return getFloat16(this, byteOffset, littleEndian); 19 | }; 20 | 21 | DataView.prototype.setFloat16 = function ( 22 | byteOffset: number, 23 | value: number, 24 | littleEndian?: boolean, 25 | ) { 26 | return setFloat16(this, byteOffset, value, littleEndian); 27 | }; 28 | 29 | (wgsl.SuffixTypedArrayMap as any).h = Float16Array; 30 | } 31 | -------------------------------------------------------------------------------- /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module '*.wgsl'; -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | 16 | /* Linting */ 17 | "strict": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "noFallthroughCasesInSwitch": true 21 | }, 22 | "include": ["src", "example", "node_modules/@webgpu/types/**/*"] 23 | } 24 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { resolve } from 'path'; 2 | import { defineConfig } from 'vite'; 3 | import dts from 'vite-plugin-dts'; 4 | 5 | export default defineConfig({ 6 | plugins: [dts()], 7 | build: { 8 | sourcemap: true, 9 | minify: false, 10 | lib: { 11 | // Could also be a dictionary or array of multiple entry points 12 | entry: resolve(__dirname, 'src/index.ts'), 13 | name: 'StructBuffer', 14 | // the proper extensions will be added 15 | fileName: 'wgsl-struct-buffer', 16 | }, 17 | }, 18 | }); 19 | --------------------------------------------------------------------------------