vitest-environment-webgpu-node 3.0.1 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,16 +1,29 @@
1
+ <p align="center">
2
+ <a href="https://npmjs.com/package/vitest-environment-webgpu-node"><img src="https://img.shields.io/npm/v/vitest-environment-webgpu-node.svg" alt="npm package"></a>
3
+ <a href="https://www.npmtrends.com/vitest-environment-webgpu-node"><img src="https://img.shields.io/npm/dw/vitest-environment-webgpu-node.svg" alt="npm downloads"></a>
4
+ <a href="https://codecov.io/gh/bhouston/vitest-gpu"><img src="https://codecov.io/gh/bhouston/vitest-gpu/branch/main/graph/badge.svg" alt="coverage"></a>
5
+ <a href="https://discord.gg/fwupDN493R"><img src="https://img.shields.io/badge/chat-discord-blue?style=flat&logo=discord" alt="discord chat"></a>
6
+ <a href="https://vitest-gpu.ben3d.ca/"><img src="https://img.shields.io/badge/docs-read-blue?style=flat" alt="documentation"></a>
7
+ </p>
8
+ <br/>
9
+
1
10
  # vitest-environment-webgpu-node
2
11
 
3
- [![npm version][npm-badge]][npm-url]
4
- [![npm downloads][downloads-badge]][npm-url]
5
- [![Tests][tests-badge]][tests-url]
6
- [![Coverage][coverage-badge]][coverage-url]
7
- [![Discord][discord-badge]][discord-url]
12
+ > Real WebGPU tests in Vitest, with no browser.
13
+
14
+ - 🖥️ Real WebGPU via Dawn
15
+ - 🚫 No Browser or Mocks
16
+ - 🧩 Headless Canvas Included
17
+ - 🔧 Dawn Backend Options
18
+ - ⚡ Up to 2.4x Faster Than Browsers
19
+
20
+ Headless GPU testing for CI: `navigator.gpu` is backed by Google's Dawn through the
21
+ [`webgpu`](https://github.com/dawn-gpu/node-webgpu) npm package. Native GPU testing is up to 2.4x faster than
22
+ running the same tests in a browser, see the [blog post](https://ben3d.ca/blog/native-gpu-testing-for-vitest-and-jest).
23
+
24
+ Part of [vitest-gpu](https://github.com/bhouston/vitest-gpu), which also provides WebGL and image snapshot packages.
8
25
 
9
- Run real WebGPU tests in Vitest on Node, without a browser, Playwright or mocks. Headless GPU testing
10
- for CI: `navigator.gpu` is backed by Google's Dawn through the
11
- [`webgpu`](https://github.com/dawn-gpu/node-webgpu) npm package. Native GPU testing is up to 2.4x faster
12
- than running the same tests in a browser, see the
13
- [blog post](https://ben3d.ca/blog/native-gpu-testing-for-vitest-and-jest).
26
+ [Read the Docs to Learn More](https://vitest-gpu.ben3d.ca/docs/webgpu/) about the WebGPU environment: Dawn options, TypeScript types, the headless canvas and CI setup.
14
27
 
15
28
  ```sh
16
29
  pnpm add -D vitest vitest-environment-webgpu-node
@@ -40,7 +53,7 @@ The environment puts `navigator.gpu` and every `GPU*` class and constant (`GPUBu
40
53
 
41
54
  Using Jest instead? See the equivalent
42
55
  [`jest-environment-webgpu-node`](https://github.com/bhouston/jest-gpu/tree/main/packages/jest-environment-webgpu-node)
43
- in [jest-gpu](https://github.com/bhouston/jest-gpu).
56
+ in [jest-gpu](https://github.com/bhouston/jest-gpu), documented at [jest-gpu.ben3d.ca](https://jest-gpu.ben3d.ca/).
44
57
 
45
58
  ## Compared to alternatives
46
59
 
@@ -56,10 +69,9 @@ Dawn in Node.
56
69
  ## Supported versions and platforms
57
70
 
58
71
  - Vitest 4 and 5 (CI tests both). Vitest 3 is not supported.
59
- - Node 22 or later. CI runs Node 22 and 26 on `macos-latest` and `ubuntu-latest`.
72
+ - Node 22 or later. CI runs Node 22 and 26 on `macos-latest`, `ubuntu-latest` and `windows-latest`.
60
73
  - Type checking needs TypeScript 6 or later (see [TypeScript types](#typescript-types)).
61
- - Linux without a GPU needs Mesa's software Vulkan driver, see [Linux and CI](#linux-and-ci). This repo's CI does
62
- not run on Windows.
74
+ - Linux without a GPU needs Mesa's software Vulkan driver, see [Linux and CI](#linux-and-ci).
63
75
 
64
76
  ## Useful for
65
77
 
@@ -159,24 +171,18 @@ Call `extendMatchers()` from it once, then pass the canvas as in the example abo
159
171
  - [`demo/`](https://github.com/bhouston/vitest-gpu/tree/main/demo/test/webgpu) for device, upload, readback, triangle, three.js, Babylon Lite and vgpu tests,
160
172
  and the [repository README](https://github.com/bhouston/vitest-gpu#readme).
161
173
 
162
- ## Author
174
+ ## Resource cleanup
163
175
 
164
- Created by [Ben Houston](https://ben3d.ca) and sponsored by [Land of Assets](https://landofassets.com).
176
+ Environment teardown destroys devices requested through its `navigator.gpu` and cancels pending callbacks scheduled through its animation-frame shim. Device requests that finish after teardown are destroyed and rejected. Devices created through another GPU instance remain the caller's responsibility. Keep disposing renderers, buffers, textures and devices during long-running files to release resources sooner.
177
+
178
+ ## Contribution
179
+
180
+ See [Contributing Guide](https://github.com/bhouston/vitest-gpu/blob/main/CONTRIBUTING.md).
165
181
 
166
182
  ## License
167
183
 
168
184
  MIT
169
185
 
170
- [npm-badge]: https://img.shields.io/npm/v/vitest-environment-webgpu-node.svg
171
- [npm-url]: https://www.npmjs.com/package/vitest-environment-webgpu-node
172
- [downloads-badge]: https://img.shields.io/npm/dm/vitest-environment-webgpu-node.svg
173
- [tests-badge]: https://github.com/bhouston/vitest-gpu/actions/workflows/ci.yml/badge.svg
174
- [tests-url]: https://github.com/bhouston/vitest-gpu/actions/workflows/ci.yml
175
- [discord-badge]: https://img.shields.io/badge/Discord-Join%20Chat-5865F2?logo=discord&logoColor=white
176
- [discord-url]: https://discord.gg/fwupDN493R
177
- [coverage-badge]: https://codecov.io/gh/bhouston/vitest-gpu/branch/main/graph/badge.svg
178
- [coverage-url]: https://codecov.io/gh/bhouston/vitest-gpu
179
-
180
- ## Resource cleanup
186
+ ## Author
181
187
 
182
- Environment teardown destroys devices requested through its `navigator.gpu` and cancels pending callbacks scheduled through its animation-frame shim. Device requests that finish after teardown are destroyed and rejected. Devices created through another GPU instance remain the caller's responsibility. Keep disposing renderers, buffers, textures and devices during long-running files to release resources sooner.
188
+ [Ben Houston](https://ben3d.ca), Sponsored by [Land of Assets](https://landofassets.com).
package/dist/canvas.d.ts CHANGED
@@ -1,7 +1,10 @@
1
1
  /** RGBA8 pixels, top row first. Feed it to `vitest-screenshot`'s `toMatchScreenshot`. */
2
2
  export type RgbaImage = {
3
+ /** Width in pixels. */
3
4
  width: number;
5
+ /** Height in pixels. */
4
6
  height: number;
7
+ /** RGBA8 bytes, four per pixel, row by row from the top. */
5
8
  data: Uint8Array;
6
9
  };
7
10
  type DefaultCanvasElement = typeof globalThis extends {
@@ -12,11 +15,30 @@ type DefaultCanvasElement = typeof globalThis extends {
12
15
  /** Minimal `GPUCanvasContext`: `getCurrentTexture()` is a texture the size of the canvas, kept until reconfigured or resized. */
13
16
  export declare class HeadlessCanvasContext {
14
17
  #private;
18
+ /** The canvas this context belongs to. */
15
19
  readonly canvas: HeadlessCanvas;
16
- constructor(canvas: HeadlessCanvas);
20
+ /**
21
+ * Creates the context for a canvas. Canvases create their own; you rarely call this.
22
+ *
23
+ * @param canvas - The canvas whose size this context's texture follows.
24
+ */
25
+ constructor(
26
+ /** The canvas this context belongs to. */
27
+ canvas: HeadlessCanvas);
28
+ /**
29
+ * Stores the configuration and discards any texture created under the previous one, as `GPUCanvasContext.configure()` does.
30
+ *
31
+ * @param config - Device, format and usage for the canvas texture.
32
+ */
17
33
  configure(config: GPUCanvasConfiguration): void;
34
+ /** Clears the configuration and discards the current texture. */
18
35
  unconfigure(): void;
36
+ /** The configuration passed to `configure()`, or `null` before it is called or after `unconfigure()`. */
19
37
  getConfiguration(): GPUCanvasConfiguration | null;
38
+ /**
39
+ * The texture the canvas renders into. It is created on first use at the canvas size and reused until the context
40
+ * is reconfigured or the canvas is resized. Throws if `configure()` has not been called.
41
+ */
20
42
  getCurrentTexture(): GPUTexture;
21
43
  /** Copies the current texture to the CPU. BGRA formats are swizzled to RGBA. */
22
44
  readPixels(): Promise<RgbaImage>;
@@ -24,31 +46,92 @@ export declare class HeadlessCanvasContext {
24
46
  /** Enough of `HTMLCanvasElement` for three.js `WebGPURenderer`, Babylon Lite and friends. */
25
47
  export declare class HeadlessCanvas {
26
48
  #private;
49
+ /** Canvas width in pixels. */
27
50
  width: number;
51
+ /** Canvas height in pixels. */
28
52
  height: number;
53
+ /** A plain object libraries can write CSS properties to; it has no effect on rendering. */
29
54
  readonly style: Record<string, string>;
30
- constructor(width?: number, height?: number);
55
+ /**
56
+ * Creates a canvas of the given size. {@link createCanvas} is the usual entry point.
57
+ *
58
+ * @param width - Canvas width in pixels.
59
+ * @param height - Canvas height in pixels.
60
+ */
61
+ constructor(
62
+ /** Canvas width in pixels. */
63
+ width?: number,
64
+ /** Canvas height in pixels. */
65
+ height?: number);
66
+ /** Same as `width`; there is no layout in Node. */
31
67
  get clientWidth(): number;
68
+ /** Same as `height`; there is no layout in Node. */
32
69
  get clientHeight(): number;
70
+ /**
71
+ * Returns the canvas's `GPUCanvasContext` for `'webgpu'`.
72
+ *
73
+ * @param id - The context type. Only `'webgpu'` is supported.
74
+ * @returns The context for `'webgpu'`, or `null` for any other type.
75
+ */
33
76
  getContext(id: 'webgpu'): HeadlessCanvasContext;
77
+ /**
78
+ * Returns the canvas's `GPUCanvasContext` for `'webgpu'`.
79
+ *
80
+ * @param id - The context type. Only `'webgpu'` is supported.
81
+ * @returns The context for `'webgpu'`, or `null` for any other type.
82
+ */
34
83
  getContext(id: string): HeadlessCanvasContext | null;
84
+ /** Reads the current texture back as RGBA8 pixels; see {@link HeadlessCanvasContext.readPixels}. */
35
85
  readPixels(): Promise<RgbaImage>;
36
- /** This same object, cast to the element type a rendering library expects. */
86
+ /**
87
+ * This same object, cast to the element type a rendering library expects.
88
+ *
89
+ * @typeParam TElement - The element type to cast to. Defaults to `HTMLCanvasElement` when DOM types are available.
90
+ */
37
91
  asElement<TElement = DefaultCanvasElement>(): TElement;
92
+ /** A rectangle at the origin with the canvas's width and height. */
38
93
  getBoundingClientRect(): {
94
+ /** Always 0. */
39
95
  x: number;
96
+ /** Always 0. */
40
97
  y: number;
98
+ /** The canvas width. */
41
99
  width: number;
100
+ /** The canvas height. */
42
101
  height: number;
102
+ /** Always 0. */
43
103
  top: number;
104
+ /** Always 0. */
44
105
  left: number;
45
106
  };
107
+ /**
108
+ * Stores an attribute on the canvas.
109
+ *
110
+ * @param name - Attribute name.
111
+ * @param value - Attribute value.
112
+ */
46
113
  setAttribute(name: string, value: string): void;
114
+ /**
115
+ * Reads an attribute stored with `setAttribute()`.
116
+ *
117
+ * @param name - Attribute name.
118
+ * @returns The stored value, or `null` if none was set.
119
+ */
47
120
  getAttribute(name: string): string | null;
121
+ /** Does nothing; present so libraries that register listeners keep working. */
48
122
  addEventListener(): void;
123
+ /** Does nothing; present so libraries that remove listeners keep working. */
49
124
  removeEventListener(): void;
125
+ /** Does nothing and returns `true`. */
50
126
  dispatchEvent(): boolean;
51
127
  }
128
+ /**
129
+ * Creates a headless canvas for WebGPU tests.
130
+ *
131
+ * @param width - Canvas width in pixels.
132
+ * @param height - Canvas height in pixels.
133
+ * @returns A {@link HeadlessCanvas}; pass `canvas.asElement()` to libraries that expect an `HTMLCanvasElement`.
134
+ */
52
135
  export declare const createCanvas: (width: number, height: number) => HeadlessCanvas;
53
136
  export {};
54
137
  //# sourceMappingURL=canvas.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"canvas.d.ts","sourceRoot":"","sources":["../src/canvas.ts"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,MAAM,MAAM,SAAS,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC;AAE5E,KAAK,oBAAoB,GAAG,OAAO,UAAU,SAAS;IACpD,iBAAiB,EAAE;QAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;KAAE,CAAC;CAClD,GACG,QAAQ,GACR,cAAc,CAAC;AAanB,iIAAiI;AACjI,qBAAa,qBAAqB;;IAIpB,QAAQ,CAAC,MAAM,EAAE,cAAc;IAA3C,YAAqB,MAAM,EAAE,cAAc,EAAI;IAE/C,SAAS,CAAC,MAAM,EAAE,sBAAsB,GAAG,IAAI,CAG9C;IAED,WAAW,IAAI,IAAI,CAGlB;IAED,gBAAgB,IAAI,sBAAsB,GAAG,IAAI,CAEhD;IAED,iBAAiB,IAAI,UAAU,CAY9B;IAED,gFAAgF;IAC1E,UAAU,IAAI,OAAO,CAAC,SAAS,CAAC,CAmCrC;CAMF;AAED,6FAA6F;AAC7F,qBAAa,cAAc;;IAMhB,KAAK;IACL,MAAM;IALf,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM;IAG5C,YACS,KAAK,SAAM,EACX,MAAM,SAAM,EACjB;IAEJ,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,UAAU,CAAC,EAAE,EAAE,QAAQ,GAAG,qBAAqB,CAAC;IAChD,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,qBAAqB,GAAG,IAAI,CAAC;IAKrD,UAAU,IAAI,OAAO,CAAC,SAAS,CAAC,CAE/B;IAED,8EAA8E;IAC9E,SAAS,CAAC,QAAQ,GAAG,oBAAoB,KAAK,QAAQ,CAErD;IAED,qBAAqB,IAAI;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAE1G;IAED,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAE9C;IAED,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAExC;IAED,gBAAgB,IAAI,IAAI,CAAG;IAC3B,mBAAmB,IAAI,IAAI,CAAG;IAC9B,aAAa,IAAI,OAAO,CAEvB;CACF;AAED,eAAO,MAAM,YAAY,UAAW,MAAM,UAAU,MAAM,KAAG,cAAmD,CAAC"}
1
+ {"version":3,"file":"canvas.d.ts","sources":["../src/canvas.ts"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,MAAM,MAAM,SAAS,GAAG;IACtB,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,wBAAwB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,IAAI,EAAE,UAAU,CAAC;CAClB,CAAC;AAEF,KAAK,oBAAoB,GAAG,OAAO,UAAU,SAAS;IACpD,iBAAiB,EAAE;QAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;KAAE,CAAC;CAClD,GACG,QAAQ,GACR,cAAc,CAAC;AAanB,iIAAiI;AACjI,qBAAa,qBAAqB;;IAU9B,0CAA0C;IAC1C,QAAQ,CAAC,MAAM,EAAE,cAAc;IAPjC;;;;OAIG;IACH;IACE,0CAA0C;IACjC,MAAM,EAAE,cAAc,EAC7B;IAEJ;;;;OAIG;IACH,SAAS,CAAC,MAAM,EAAE,sBAAsB,GAAG,IAAI,CAG9C;IAED,iEAAiE;IACjE,WAAW,IAAI,IAAI,CAGlB;IAED,yGAAyG;IACzG,gBAAgB,IAAI,sBAAsB,GAAG,IAAI,CAEhD;IAED;;;OAGG;IACH,iBAAiB,IAAI,UAAU,CAY9B;IAED,gFAAgF;IAC1E,UAAU,IAAI,OAAO,CAAC,SAAS,CAAC,CAmCrC;CAMF;AAED,6FAA6F;AAC7F,qBAAa,cAAc;;IAavB,8BAA8B;IACvB,KAAK;IACZ,+BAA+B;IACxB,MAAM;IAdf,2FAA2F;IAC3F,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM;IAG5C;;;;;OAKG;IACH;IACE,8BAA8B;IACvB,KAAK,SAAM;IAClB,+BAA+B;IACxB,MAAM,SAAM,EACjB;IAEJ,mDAAmD;IACnD,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,oDAAoD;IACpD,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED;;;;;OAKG;IACH,UAAU,CAAC,EAAE,EAAE,QAAQ,GAAG,qBAAqB,CAAC;IAChD;;;;;OAKG;IACH,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,qBAAqB,GAAG,IAAI,CAAC;IAKrD,oGAAoG;IACpG,UAAU,IAAI,OAAO,CAAC,SAAS,CAAC,CAE/B;IAED;;;;OAIG;IACH,SAAS,CAAC,QAAQ,GAAG,oBAAoB,KAAK,QAAQ,CAErD;IAED,oEAAoE;IACpE,qBAAqB,IAAI;QACvB,gBAAgB;QAChB,CAAC,EAAE,MAAM,CAAC;QACV,gBAAgB;QAChB,CAAC,EAAE,MAAM,CAAC;QACV,wBAAwB;QACxB,KAAK,EAAE,MAAM,CAAC;QACd,yBAAyB;QACzB,MAAM,EAAE,MAAM,CAAC;QACf,gBAAgB;QAChB,GAAG,EAAE,MAAM,CAAC;QACZ,gBAAgB;QAChB,IAAI,EAAE,MAAM,CAAC;KACd,CAEA;IAED;;;;;OAKG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAE9C;IAED;;;;;OAKG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAExC;IAED,+EAA+E;IAC/E,gBAAgB,IAAI,IAAI,CAAG;IAC3B,6EAA6E;IAC7E,mBAAmB,IAAI,IAAI,CAAG;IAC9B,uCAAuC;IACvC,aAAa,IAAI,OAAO,CAEvB;CACF;AAED;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,UAAW,MAAM,UAAU,MAAM,KAAG,cAAmD,CAAC"}
package/dist/canvas.js CHANGED
@@ -13,20 +13,38 @@ export class HeadlessCanvasContext {
13
13
  canvas;
14
14
  #config;
15
15
  #texture;
16
- constructor(canvas) {
16
+ /**
17
+ * Creates the context for a canvas. Canvases create their own; you rarely call this.
18
+ *
19
+ * @param canvas - The canvas whose size this context's texture follows.
20
+ */
21
+ constructor(
22
+ /** The canvas this context belongs to. */
23
+ canvas) {
17
24
  this.canvas = canvas;
18
25
  }
26
+ /**
27
+ * Stores the configuration and discards any texture created under the previous one, as `GPUCanvasContext.configure()` does.
28
+ *
29
+ * @param config - Device, format and usage for the canvas texture.
30
+ */
19
31
  configure(config) {
20
32
  this.#config = config;
21
33
  this.#drop();
22
34
  }
35
+ /** Clears the configuration and discards the current texture. */
23
36
  unconfigure() {
24
37
  this.#config = undefined;
25
38
  this.#drop();
26
39
  }
40
+ /** The configuration passed to `configure()`, or `null` before it is called or after `unconfigure()`. */
27
41
  getConfiguration() {
28
42
  return this.#config ?? null;
29
43
  }
44
+ /**
45
+ * The texture the canvas renders into. It is created on first use at the canvas size and reused until the context
46
+ * is reconfigured or the canvas is resized. Throws if `configure()` has not been called.
47
+ */
30
48
  getCurrentTexture() {
31
49
  const config = this.#config;
32
50
  if (!config)
@@ -92,42 +110,83 @@ export class HeadlessCanvas {
92
110
  width;
93
111
  height;
94
112
  #context = new HeadlessCanvasContext(this);
113
+ /** A plain object libraries can write CSS properties to; it has no effect on rendering. */
95
114
  style = {};
96
115
  #attributes = new Map();
97
- constructor(width = 300, height = 150) {
116
+ /**
117
+ * Creates a canvas of the given size. {@link createCanvas} is the usual entry point.
118
+ *
119
+ * @param width - Canvas width in pixels.
120
+ * @param height - Canvas height in pixels.
121
+ */
122
+ constructor(
123
+ /** Canvas width in pixels. */
124
+ width = 300,
125
+ /** Canvas height in pixels. */
126
+ height = 150) {
98
127
  this.width = width;
99
128
  this.height = height;
100
129
  }
130
+ /** Same as `width`; there is no layout in Node. */
101
131
  get clientWidth() {
102
132
  return this.width;
103
133
  }
134
+ /** Same as `height`; there is no layout in Node. */
104
135
  get clientHeight() {
105
136
  return this.height;
106
137
  }
107
138
  getContext(id) {
108
139
  return id === 'webgpu' ? this.#context : null;
109
140
  }
141
+ /** Reads the current texture back as RGBA8 pixels; see {@link HeadlessCanvasContext.readPixels}. */
110
142
  readPixels() {
111
143
  return this.#context.readPixels();
112
144
  }
113
- /** This same object, cast to the element type a rendering library expects. */
145
+ /**
146
+ * This same object, cast to the element type a rendering library expects.
147
+ *
148
+ * @typeParam TElement - The element type to cast to. Defaults to `HTMLCanvasElement` when DOM types are available.
149
+ */
114
150
  asElement() {
115
151
  return this;
116
152
  }
153
+ /** A rectangle at the origin with the canvas's width and height. */
117
154
  getBoundingClientRect() {
118
155
  return { x: 0, y: 0, top: 0, left: 0, width: this.width, height: this.height };
119
156
  }
157
+ /**
158
+ * Stores an attribute on the canvas.
159
+ *
160
+ * @param name - Attribute name.
161
+ * @param value - Attribute value.
162
+ */
120
163
  setAttribute(name, value) {
121
164
  this.#attributes.set(name, value);
122
165
  }
166
+ /**
167
+ * Reads an attribute stored with `setAttribute()`.
168
+ *
169
+ * @param name - Attribute name.
170
+ * @returns The stored value, or `null` if none was set.
171
+ */
123
172
  getAttribute(name) {
124
173
  return this.#attributes.get(name) ?? null;
125
174
  }
175
+ /** Does nothing; present so libraries that register listeners keep working. */
126
176
  addEventListener() { }
177
+ /** Does nothing; present so libraries that remove listeners keep working. */
127
178
  removeEventListener() { }
179
+ /** Does nothing and returns `true`. */
128
180
  dispatchEvent() {
129
181
  return true;
130
182
  }
131
183
  }
184
+ /**
185
+ * Creates a headless canvas for WebGPU tests.
186
+ *
187
+ * @param width - Canvas width in pixels.
188
+ * @param height - Canvas height in pixels.
189
+ * @returns A {@link HeadlessCanvas}; pass `canvas.asElement()` to libraries that expect an `HTMLCanvasElement`.
190
+ */
132
191
  export const createCanvas = (width, height) => new HeadlessCanvas(width, height);
133
192
  //# sourceMappingURL=canvas.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"canvas.js","sourceRoot":"","sources":["../src/canvas.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"canvas.js","sources":["../src/canvas.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -4,13 +4,33 @@ export type WebgpuNodeOptions = {
4
4
  /** Dawn options, e.g. `['backend=vulkan', 'enable-dawn-features=allow_unsafe_apis']`. */
5
5
  dawnOptions?: string[];
6
6
  };
7
+ /**
8
+ * The Vitest environment registered as `webgpu-node`. Before each test file it puts `navigator.gpu`, the `GPU*`
9
+ * classes and constants, and minimal `window`, `document`, `HTMLCanvasElement` and `requestAnimationFrame` shims
10
+ * on the global object (only where missing), and it removes them afterwards.
11
+ */
7
12
  declare const _default: {
13
+ /** The name Vitest uses to select this environment: `test.environment: 'webgpu-node'`. */
8
14
  name: string;
15
+ /** Runs test files through Vite's `ssr` environment, as Node code. */
9
16
  viteEnvironment: "ssr";
17
+ /**
18
+ * Creates the Dawn-backed `navigator.gpu` and installs the DOM shims on the test file's global object.
19
+ *
20
+ * @param global - The global object of the test file's context.
21
+ * @param __namedParameters - The environment options from the Vitest config; `webgpuNode` holds {@link WebgpuNodeOptions}.
22
+ * @returns A `teardown` hook that destroys the devices this environment created and restores the globals.
23
+ */
10
24
  setup(global: Record<string, unknown>, { webgpuNode }: {
11
25
  webgpuNode?: WebgpuNodeOptions;
12
26
  }): {
13
- teardown(_global?: Record<string, unknown>): void;
27
+ /**
28
+ * Destroys the GPU devices requested through this environment, cancels pending animation-frame callbacks and
29
+ * removes the globals that `setup` added.
30
+ *
31
+ * @param _global - Unused; teardown restores the global object it captured in `setup`.
32
+ */
33
+ teardown: (_global?: Record<string, unknown>) => void;
14
34
  };
15
35
  };
16
36
  export default _default;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,qBAAqB,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAElG,4EAA4E;AAC5E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,yFAAyF;IACzF,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB,CAAC;;;;kBA2Dc,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,kBAAuB;QAAE,UAAU,CAAC,EAAE,iBAAiB,CAAA;KAAE;2BA4DvE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,qBAAqB,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAElG,4EAA4E;AAC5E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,yFAAyF;IACzF,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB,CAAC;AAwDF;;;;GAIG;;IAED,0FAA0F;;IAE1F,sEAAsE;;IAEtE;;;;;;OAMG;kBACW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,kBAAuB;QAAE,UAAU,CAAC,EAAE,iBAAiB,CAAA;KAAE;QA6D1F;;;;;WAKG;6BACkB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;AA/ElD,wBA0FwB"}
package/dist/index.js CHANGED
@@ -55,11 +55,26 @@ const restore = (properties) => {
55
55
  Reflect.deleteProperty(target, key);
56
56
  }
57
57
  };
58
+ /**
59
+ * The Vitest environment registered as `webgpu-node`. Before each test file it puts `navigator.gpu`, the `GPU*`
60
+ * classes and constants, and minimal `window`, `document`, `HTMLCanvasElement` and `requestAnimationFrame` shims
61
+ * on the global object (only where missing), and it removes them afterwards.
62
+ */
58
63
  export default {
64
+ /** The name Vitest uses to select this environment: `test.environment: 'webgpu-node'`. */
59
65
  name: 'webgpu-node',
66
+ /** Runs test files through Vite's `ssr` environment, as Node code. */
60
67
  viteEnvironment: 'ssr',
68
+ /**
69
+ * Creates the Dawn-backed `navigator.gpu` and installs the DOM shims on the test file's global object.
70
+ *
71
+ * @param global - The global object of the test file's context.
72
+ * @param __namedParameters - The environment options from the Vitest config; `webgpuNode` holds {@link WebgpuNodeOptions}.
73
+ * @returns A `teardown` hook that destroys the devices this environment created and restores the globals.
74
+ */
61
75
  setup(global, { webgpuNode = {} }) {
62
76
  const dom = domShims();
77
+ // oxlint-disable-next-line typescript/no-misused-spread -- intentionally copies the own enumerable GPU* globals
63
78
  const shims = { ...globals, ...dom.shims };
64
79
  const devices = new Set();
65
80
  let disposed = false;
@@ -123,7 +138,13 @@ export default {
123
138
  throw error;
124
139
  }
125
140
  return {
126
- teardown(_global) {
141
+ /**
142
+ * Destroys the GPU devices requested through this environment, cancels pending animation-frame callbacks and
143
+ * removes the globals that `setup` added.
144
+ *
145
+ * @param _global - Unused; teardown restores the global object it captured in `setup`.
146
+ */
147
+ teardown: (_global) => {
127
148
  if (disposed)
128
149
  return;
129
150
  try {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vitest-environment-webgpu-node",
3
- "version": "3.0.1",
3
+ "version": "3.0.2",
4
4
  "description": "Vitest environment for real headless WebGPU tests in Node (Dawn via the webgpu package): no browser, Playwright or mocks",
5
5
  "keywords": [
6
6
  "ci",
@@ -50,7 +50,10 @@
50
50
  "access": "public"
51
51
  },
52
52
  "dependencies": {
53
- "webgpu": "^0.6.1"
53
+ "webgpu": "^0.6.2"
54
+ },
55
+ "devDependencies": {
56
+ "typescript": "7.1.0-beta"
54
57
  },
55
58
  "peerDependencies": {
56
59
  "typescript": ">=6",
@@ -65,7 +68,7 @@
65
68
  "node": ">=22"
66
69
  },
67
70
  "scripts": {
68
- "build": "tsc",
69
- "tsc": "tsc"
71
+ "build": "tsc -p tsconfig.build.json",
72
+ "tsc": "tsc --noEmit"
70
73
  }
71
74
  }
package/src/canvas.ts CHANGED
@@ -1,5 +1,12 @@
1
1
  /** RGBA8 pixels, top row first. Feed it to `vitest-screenshot`'s `toMatchScreenshot`. */
2
- export type RgbaImage = { width: number; height: number; data: Uint8Array };
2
+ export type RgbaImage = {
3
+ /** Width in pixels. */
4
+ width: number;
5
+ /** Height in pixels. */
6
+ height: number;
7
+ /** RGBA8 bytes, four per pixel, row by row from the top. */
8
+ data: Uint8Array;
9
+ };
3
10
 
4
11
  type DefaultCanvasElement = typeof globalThis extends {
5
12
  HTMLCanvasElement: { prototype: infer TElement };
@@ -23,22 +30,41 @@ export class HeadlessCanvasContext {
23
30
  #config: GPUCanvasConfiguration | undefined;
24
31
  #texture: GPUTexture | undefined;
25
32
 
26
- constructor(readonly canvas: HeadlessCanvas) {}
33
+ /**
34
+ * Creates the context for a canvas. Canvases create their own; you rarely call this.
35
+ *
36
+ * @param canvas - The canvas whose size this context's texture follows.
37
+ */
38
+ constructor(
39
+ /** The canvas this context belongs to. */
40
+ readonly canvas: HeadlessCanvas,
41
+ ) {}
27
42
 
43
+ /**
44
+ * Stores the configuration and discards any texture created under the previous one, as `GPUCanvasContext.configure()` does.
45
+ *
46
+ * @param config - Device, format and usage for the canvas texture.
47
+ */
28
48
  configure(config: GPUCanvasConfiguration): void {
29
49
  this.#config = config;
30
50
  this.#drop();
31
51
  }
32
52
 
53
+ /** Clears the configuration and discards the current texture. */
33
54
  unconfigure(): void {
34
55
  this.#config = undefined;
35
56
  this.#drop();
36
57
  }
37
58
 
59
+ /** The configuration passed to `configure()`, or `null` before it is called or after `unconfigure()`. */
38
60
  getConfiguration(): GPUCanvasConfiguration | null {
39
61
  return this.#config ?? null;
40
62
  }
41
63
 
64
+ /**
65
+ * The texture the canvas renders into. It is created on first use at the canvas size and reused until the context
66
+ * is reconfigured or the canvas is resized. Throws if `configure()` has not been called.
67
+ */
42
68
  getCurrentTexture(): GPUTexture {
43
69
  const config = this.#config;
44
70
  if (!config) throw new Error('getCurrentTexture() called before configure()');
@@ -100,54 +126,118 @@ export class HeadlessCanvasContext {
100
126
  /** Enough of `HTMLCanvasElement` for three.js `WebGPURenderer`, Babylon Lite and friends. */
101
127
  export class HeadlessCanvas {
102
128
  readonly #context = new HeadlessCanvasContext(this);
129
+ /** A plain object libraries can write CSS properties to; it has no effect on rendering. */
103
130
  readonly style: Record<string, string> = {};
104
131
  readonly #attributes = new Map<string, string>();
105
132
 
133
+ /**
134
+ * Creates a canvas of the given size. {@link createCanvas} is the usual entry point.
135
+ *
136
+ * @param width - Canvas width in pixels.
137
+ * @param height - Canvas height in pixels.
138
+ */
106
139
  constructor(
140
+ /** Canvas width in pixels. */
107
141
  public width = 300,
142
+ /** Canvas height in pixels. */
108
143
  public height = 150,
109
144
  ) {}
110
145
 
146
+ /** Same as `width`; there is no layout in Node. */
111
147
  get clientWidth(): number {
112
148
  return this.width;
113
149
  }
114
150
 
151
+ /** Same as `height`; there is no layout in Node. */
115
152
  get clientHeight(): number {
116
153
  return this.height;
117
154
  }
118
155
 
156
+ /**
157
+ * Returns the canvas's `GPUCanvasContext` for `'webgpu'`.
158
+ *
159
+ * @param id - The context type. Only `'webgpu'` is supported.
160
+ * @returns The context for `'webgpu'`, or `null` for any other type.
161
+ */
119
162
  getContext(id: 'webgpu'): HeadlessCanvasContext;
163
+ /**
164
+ * Returns the canvas's `GPUCanvasContext` for `'webgpu'`.
165
+ *
166
+ * @param id - The context type. Only `'webgpu'` is supported.
167
+ * @returns The context for `'webgpu'`, or `null` for any other type.
168
+ */
120
169
  getContext(id: string): HeadlessCanvasContext | null;
121
170
  getContext(id: string): HeadlessCanvasContext | null {
122
171
  return id === 'webgpu' ? this.#context : null;
123
172
  }
124
173
 
174
+ /** Reads the current texture back as RGBA8 pixels; see {@link HeadlessCanvasContext.readPixels}. */
125
175
  readPixels(): Promise<RgbaImage> {
126
176
  return this.#context.readPixels();
127
177
  }
128
178
 
129
- /** This same object, cast to the element type a rendering library expects. */
179
+ /**
180
+ * This same object, cast to the element type a rendering library expects.
181
+ *
182
+ * @typeParam TElement - The element type to cast to. Defaults to `HTMLCanvasElement` when DOM types are available.
183
+ */
130
184
  asElement<TElement = DefaultCanvasElement>(): TElement {
131
185
  return this as unknown as TElement;
132
186
  }
133
187
 
134
- getBoundingClientRect(): { x: number; y: number; width: number; height: number; top: number; left: number } {
188
+ /** A rectangle at the origin with the canvas's width and height. */
189
+ getBoundingClientRect(): {
190
+ /** Always 0. */
191
+ x: number;
192
+ /** Always 0. */
193
+ y: number;
194
+ /** The canvas width. */
195
+ width: number;
196
+ /** The canvas height. */
197
+ height: number;
198
+ /** Always 0. */
199
+ top: number;
200
+ /** Always 0. */
201
+ left: number;
202
+ } {
135
203
  return { x: 0, y: 0, top: 0, left: 0, width: this.width, height: this.height };
136
204
  }
137
205
 
206
+ /**
207
+ * Stores an attribute on the canvas.
208
+ *
209
+ * @param name - Attribute name.
210
+ * @param value - Attribute value.
211
+ */
138
212
  setAttribute(name: string, value: string): void {
139
213
  this.#attributes.set(name, value);
140
214
  }
141
215
 
216
+ /**
217
+ * Reads an attribute stored with `setAttribute()`.
218
+ *
219
+ * @param name - Attribute name.
220
+ * @returns The stored value, or `null` if none was set.
221
+ */
142
222
  getAttribute(name: string): string | null {
143
223
  return this.#attributes.get(name) ?? null;
144
224
  }
145
225
 
226
+ /** Does nothing; present so libraries that register listeners keep working. */
146
227
  addEventListener(): void {}
228
+ /** Does nothing; present so libraries that remove listeners keep working. */
147
229
  removeEventListener(): void {}
230
+ /** Does nothing and returns `true`. */
148
231
  dispatchEvent(): boolean {
149
232
  return true;
150
233
  }
151
234
  }
152
235
 
236
+ /**
237
+ * Creates a headless canvas for WebGPU tests.
238
+ *
239
+ * @param width - Canvas width in pixels.
240
+ * @param height - Canvas height in pixels.
241
+ * @returns A {@link HeadlessCanvas}; pass `canvas.asElement()` to libraries that expect an `HTMLCanvasElement`.
242
+ */
153
243
  export const createCanvas = (width: number, height: number): HeadlessCanvas => new HeadlessCanvas(width, height);
package/src/index.ts CHANGED
@@ -64,11 +64,26 @@ const restore = (properties: SavedProperty[]): void => {
64
64
  }
65
65
  };
66
66
 
67
+ /**
68
+ * The Vitest environment registered as `webgpu-node`. Before each test file it puts `navigator.gpu`, the `GPU*`
69
+ * classes and constants, and minimal `window`, `document`, `HTMLCanvasElement` and `requestAnimationFrame` shims
70
+ * on the global object (only where missing), and it removes them afterwards.
71
+ */
67
72
  export default {
73
+ /** The name Vitest uses to select this environment: `test.environment: 'webgpu-node'`. */
68
74
  name: 'webgpu-node',
75
+ /** Runs test files through Vite's `ssr` environment, as Node code. */
69
76
  viteEnvironment: 'ssr',
77
+ /**
78
+ * Creates the Dawn-backed `navigator.gpu` and installs the DOM shims on the test file's global object.
79
+ *
80
+ * @param global - The global object of the test file's context.
81
+ * @param __namedParameters - The environment options from the Vitest config; `webgpuNode` holds {@link WebgpuNodeOptions}.
82
+ * @returns A `teardown` hook that destroys the devices this environment created and restores the globals.
83
+ */
70
84
  setup(global: Record<string, unknown>, { webgpuNode = {} }: { webgpuNode?: WebgpuNodeOptions }) {
71
85
  const dom = domShims();
86
+ // oxlint-disable-next-line typescript/no-misused-spread -- intentionally copies the own enumerable GPU* globals
72
87
  const shims = { ...globals, ...dom.shims } as Record<string, unknown>;
73
88
  const devices = new Set<GPUDevice>();
74
89
  let disposed = false;
@@ -127,7 +142,13 @@ export default {
127
142
  throw error;
128
143
  }
129
144
  return {
130
- teardown(_global?: Record<string, unknown>) {
145
+ /**
146
+ * Destroys the GPU devices requested through this environment, cancels pending animation-frame callbacks and
147
+ * removes the globals that `setup` added.
148
+ *
149
+ * @param _global - Unused; teardown restores the global object it captured in `setup`.
150
+ */
151
+ teardown: (_global?: Record<string, unknown>) => {
131
152
  if (disposed) return;
132
153
  try {
133
154
  dispose();