vitest-pool-assemblyscript 0.2.0

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.
Files changed (83) hide show
  1. package/BINARYEN_VERSION +1 -0
  2. package/LICENSE +53 -0
  3. package/README.md +607 -0
  4. package/assembly/compare.ts +219 -0
  5. package/assembly/describe.ts +104 -0
  6. package/assembly/expect.ts +335 -0
  7. package/assembly/index.ts +14 -0
  8. package/assembly/options.ts +198 -0
  9. package/assembly/test.ts +147 -0
  10. package/assembly/tsconfig.json +6 -0
  11. package/binding.gyp +62 -0
  12. package/dist/ast-visitor-DC3SuTzs.mjs +310 -0
  13. package/dist/ast-visitor-DC3SuTzs.mjs.map +1 -0
  14. package/dist/compile-runner-8h0dBwG2.mjs +80 -0
  15. package/dist/compile-runner-8h0dBwG2.mjs.map +1 -0
  16. package/dist/compiler/transforms/strip-inline.d.mts +18 -0
  17. package/dist/compiler/transforms/strip-inline.d.mts.map +1 -0
  18. package/dist/compiler/transforms/strip-inline.mjs +38 -0
  19. package/dist/compiler/transforms/strip-inline.mjs.map +1 -0
  20. package/dist/compiler-CN6BRK_N.mjs +295 -0
  21. package/dist/compiler-CN6BRK_N.mjs.map +1 -0
  22. package/dist/config/index-v3.d.mts +111 -0
  23. package/dist/config/index-v3.d.mts.map +1 -0
  24. package/dist/config/index-v3.mjs +11 -0
  25. package/dist/config/index-v3.mjs.map +1 -0
  26. package/dist/config/index.d.mts +4 -0
  27. package/dist/config/index.mjs +8 -0
  28. package/dist/constants-CA50WBdr.mjs +130 -0
  29. package/dist/constants-CA50WBdr.mjs.map +1 -0
  30. package/dist/coverage-merge-0WqdC-dq.mjs +22 -0
  31. package/dist/coverage-merge-0WqdC-dq.mjs.map +1 -0
  32. package/dist/coverage-provider/index.d.mts +15 -0
  33. package/dist/coverage-provider/index.d.mts.map +1 -0
  34. package/dist/coverage-provider/index.mjs +535 -0
  35. package/dist/coverage-provider/index.mjs.map +1 -0
  36. package/dist/custom-provider-options-CF5C1kXb.d.mts +26 -0
  37. package/dist/custom-provider-options-CF5C1kXb.d.mts.map +1 -0
  38. package/dist/debug-IeEHsxy0.mjs +195 -0
  39. package/dist/debug-IeEHsxy0.mjs.map +1 -0
  40. package/dist/index-internal.d.mts +23 -0
  41. package/dist/index-internal.d.mts.map +1 -0
  42. package/dist/index-internal.mjs +4 -0
  43. package/dist/index-v3.d.mts +7 -0
  44. package/dist/index-v3.d.mts.map +1 -0
  45. package/dist/index-v3.mjs +206 -0
  46. package/dist/index-v3.mjs.map +1 -0
  47. package/dist/index.d.mts +3 -0
  48. package/dist/index.mjs +8 -0
  49. package/dist/load-user-imports-J9eaAW0_.mjs +801 -0
  50. package/dist/load-user-imports-J9eaAW0_.mjs.map +1 -0
  51. package/dist/pool-runner-init-CEwLyNI3.d.mts +8 -0
  52. package/dist/pool-runner-init-CEwLyNI3.d.mts.map +1 -0
  53. package/dist/pool-runner-init-d5qScS41.mjs +400 -0
  54. package/dist/pool-runner-init-d5qScS41.mjs.map +1 -0
  55. package/dist/pool-thread/compile-worker-thread.d.mts +7 -0
  56. package/dist/pool-thread/compile-worker-thread.d.mts.map +1 -0
  57. package/dist/pool-thread/compile-worker-thread.mjs +42 -0
  58. package/dist/pool-thread/compile-worker-thread.mjs.map +1 -0
  59. package/dist/pool-thread/test-worker-thread.d.mts +7 -0
  60. package/dist/pool-thread/test-worker-thread.d.mts.map +1 -0
  61. package/dist/pool-thread/test-worker-thread.mjs +39 -0
  62. package/dist/pool-thread/test-worker-thread.mjs.map +1 -0
  63. package/dist/pool-thread/v3-tinypool-thread.d.mts +7 -0
  64. package/dist/pool-thread/v3-tinypool-thread.d.mts.map +1 -0
  65. package/dist/pool-thread/v3-tinypool-thread.mjs +57 -0
  66. package/dist/pool-thread/v3-tinypool-thread.mjs.map +1 -0
  67. package/dist/resolve-config-as1w-Qyz.mjs +65 -0
  68. package/dist/resolve-config-as1w-Qyz.mjs.map +1 -0
  69. package/dist/test-runner-B2BpyPNK.mjs +142 -0
  70. package/dist/test-runner-B2BpyPNK.mjs.map +1 -0
  71. package/dist/types-8KKo9Hbf.d.mts +228 -0
  72. package/dist/types-8KKo9Hbf.d.mts.map +1 -0
  73. package/dist/vitest-file-tasks-BUwzh375.mjs +61 -0
  74. package/dist/vitest-file-tasks-BUwzh375.mjs.map +1 -0
  75. package/dist/vitest-tasks-BKS7689f.mjs +319 -0
  76. package/dist/vitest-tasks-BKS7689f.mjs.map +1 -0
  77. package/dist/worker-rpc-channel-lbhK7Qz8.mjs +25 -0
  78. package/dist/worker-rpc-channel-lbhK7Qz8.mjs.map +1 -0
  79. package/package.json +112 -0
  80. package/prebuilds/linux-x64/vitest-pool-assemblyscript.glibc.node +0 -0
  81. package/scripts/install.js +91 -0
  82. package/scripts/setup-binaryen.js +179 -0
  83. package/src/native-instrumentation/addon.cpp +788 -0
@@ -0,0 +1 @@
1
+ version_124
package/LICENSE ADDED
@@ -0,0 +1,53 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 - 2026 Matt Ritter
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ ===============================================================================
24
+
25
+ Portions of this software have been derived from third-party works which are
26
+ licenced under different terms. Individual code contributions have been
27
+ noted where applicable and are accompanied by their respective licenses.
28
+
29
+ Additionally, the following third-party works are utilized:
30
+
31
+ * AssemblyScript: https://github.com/AssemblyScript/assemblyscript
32
+
33
+ Apache License, Version 2.0 (https://opensource.org/licenses/Apache-2.0)
34
+
35
+ * TypeScript: https://github.com/Microsoft/TypeScript
36
+
37
+ Copyright (c) Microsoft Corporation
38
+ Apache License, Version 2.0 (https://opensource.org/licenses/Apache-2.0)
39
+
40
+ * Binaryen: https://github.com/WebAssembly/binaryen
41
+
42
+ Copyright (c) WebAssembly Community Group participants
43
+ Apache License, Version 2.0 (https://opensource.org/licenses/Apache-2.0)
44
+
45
+ * source-map: https://github.com/mozilla/source-map
46
+
47
+ Copyright (c) 2009-2011, Mozilla Foundation and contributors
48
+ BSD Licence, 3-Clause Version (https://opensource.org/license/bsd-3-clause)
49
+
50
+ * istanbul-lib-coverage: https://github.com/istanbuljs/istanbuljs
51
+
52
+ Copyright 2012-2015 Yahoo! Inc.
53
+ BSD Licence, 3-Clause Version (https://opensource.org/license/bsd-3-clause)
package/README.md ADDED
@@ -0,0 +1,607 @@
1
+ # vitest-pool-assemblyscript
2
+
3
+ AssemblyScript unit testing for your Vitest workflow: Simple, fast, familiar, AS-native.
4
+
5
+ This is a [Vitest](https://vitest.dev) ["custom pool"](https://vitest.dev/guide/advanced/pool.html) which knows how to compile AssemblyScript to WASM, harness WASM to run tests, and report those results to vitest. It co-exists with existing JavaScript/TypeScript tests, and is designed for incremental adoption.
6
+
7
+ - [Quickstart](#quickstart)
8
+ - [Features](#features)
9
+ - [Configuration](#configuration)
10
+ - [Writing Tests](#writing-tests)
11
+ - [Matcher API](#matcher-api)
12
+ - [Project Status & Expectations](#project-status--expectations)
13
+ - [Installation Guide (Development Preview)](#installation-guide-development-preview)
14
+
15
+ **Note: 🚧 This project is currently *Pre-Release, Pre-v1, Under Active Development* 🚧**
16
+ - See [Project Status & Expectations](#project-status--expectations) for what's working now, and to see what's planned!
17
+
18
+ ---
19
+
20
+ ## Quickstart
21
+
22
+ Coming Soon!
23
+
24
+ ---
25
+
26
+ ## Features
27
+
28
+ ### Vitest Integration
29
+ - Use familiar `vitest` commands, CLI spec and test filtering, watch mode
30
+ - Works with Vitest UI, reporters, and coverage tools
31
+ - Project (workspace) config allows coexisting AssemblyScript pools and JavaScript pools
32
+ - Hybrid Coverage Provider unifies test reports from multiple pools (delegating to v8 for JS/TS coverage)
33
+ - Coverage reporting using any vitest reporter (`html`, `lcov`, `json`, etc)
34
+ - Dual vitest 3.x / 4.x support
35
+
36
+ ### Per-Test WASM Isolation
37
+ - Each AssemblyScript test file is compiled to a WASM binary once
38
+ - Each test case runs in a fresh WASM instance (reusing the compiled binary)
39
+ - One crashing test doesn't kill the rest within the same suite
40
+ - `toThrowError()` matcher can be used to catch and expect specific errors (which trap and abort)
41
+
42
+ ### Familiar Developer Experience
43
+ - Suite and test definition using `describe()` and `test()` in AssemblyScript
44
+ - Inline test option configuration for common vitest options: `timeout`, `retry`, `skip`, `only`, `fails`
45
+ - Assertion matching API based on vitest/jest `expect()` API. See [Matcher API](#matcher-api) for the set of supported matchers and differences from JavaScript
46
+ - Highlighted diffs for assertion and runtime failures, which point to source code
47
+ - Source-mapped WASM error stack traces (accurate source `function file:line:column`)
48
+ - AssemblyScript console output captured and provided to vitest for display
49
+ - No boilerplate patterns for: `run()`, `endTest()`, `fs.readFile`, `WebAssembly.Instance`, etc
50
+
51
+ ### Performance & Customization
52
+ - Parallel execution thread pool
53
+ - Lightweight coverage instrumentation using separate memory
54
+ - In-memory binaries and source maps for minimal file I/O
55
+ - Coverage for inlined (`@inline`) code
56
+ - Enforced hard timeouts for long-running WASM via thread termination, with intelligent resume
57
+ - Configurable AssemblyScript compiler options
58
+ - Configurable test memory size
59
+ - Configurable WASM imports with access to memory
60
+
61
+ ### Why This Over [Alternative]?
62
+
63
+ There are other standalone testing frameworks for AssemblyScript testing, including:
64
+ - [assemblyscript-unittest-framework](https://github.com/wasm-ecosystem/assemblyscript-unittest-framework): A full-featured AS test framework
65
+ - Many thanks owed to this project for inspiring parts of our discovery and instrumentation approach
66
+ - [as-test](https://github.com/JairusSW/as-test): A minimal and fast AssemblyScript test framework and runner
67
+ - [Built with AssemblyScript - Testing & Benchmarking](https://www.assemblyscript.org/built-with-assemblyscript.html#testing-benchmarking) may track more
68
+
69
+ ---
70
+
71
+ ## Configuration
72
+
73
+ In your project's `vitest.config.ts`:
74
+ - The `test` project configuration helpers needed depend on which version of vitest you're using.
75
+ - The `coverage` configuration is the same across versions (shown in the first example below).
76
+
77
+ ### vitest 4.x.x Multiple-Project Config:
78
+ ```typescript
79
+ import { defineConfig, defineProject } from 'vitest/config';
80
+ import { createAssemblyScriptPool } from 'vitest-pool-assemblyscript/config';
81
+
82
+ export default defineConfig({
83
+ test: {
84
+ projects: [
85
+ // AssemblyScript project
86
+ defineProject({
87
+ test: {
88
+ name: {
89
+ label: 'assemblyscript-tests',
90
+ color: 'yellow'
91
+ },
92
+ include: ['test/assembly/**/*.as.{test,spec}.ts'],
93
+
94
+ // supported vitest options
95
+ bail: 2, // stop test run after this many failures
96
+ retry: 0, // number of retries to attempt after initial failure
97
+ testTimeout: 500, // ms to wait before terminating test
98
+ // allowOnly: true, // whether or not to respect test.only and describe.only
99
+ // maxWorkers: 8, // concurrent file execution threads (default: available parallelism)
100
+
101
+ // configure vitest to use this custom pool for test files in `include`
102
+ pool: createAssemblyScriptPool({
103
+ stripInline: true, // true to remove @inline decorators for coverage (default: true)
104
+ testMemoryPagesInitial: 2, // initial WASM memory size in pages (default: 1)
105
+ testMemoryPagesMax: 4, // maximum WASM memory size in pages (default: undefined)
106
+ extraCompilerFlags: ['--runtime', 'incremental'], // additional asc flags to customize AS compilation
107
+ wasmImportsFactory: 'test-helpers/create-imports.js', // factory function to create your own WASM imports
108
+ }),
109
+ }
110
+ }),
111
+
112
+ // JavaScript/TypeScript project
113
+ defineProject({
114
+ test: {
115
+ name: {
116
+ label: 'javascript-typescript-tests',
117
+ color: 'blue'
118
+ },
119
+ include: ['test/js/*.{test,spec}.{ts,js}'],
120
+ }
121
+ }),
122
+ ]
123
+ },
124
+
125
+ // Coverage config must be at root level (applies to all projects).
126
+ // The "hybrid" provider delegates JS to v8, and merges AS coverage into the final report
127
+ coverage: {
128
+ provider: 'custom',
129
+ customProviderModule: 'vitest-pool-assemblyscript/coverage',
130
+ assemblyScriptInclude: ['assembly/**/*.ts'], // example, include AS sources to report on
131
+ assemblyScriptExclude: ['assembly/helpers/*.ts'], // example, exclude AS sources from reporting
132
+
133
+ // all other v8 coverage options will be passed through to delegated v8 provider
134
+ enabled: true,
135
+ cleanOnRerun: true,
136
+ reportsDirectory: './coverage',
137
+ reporter: ['text', 'lcov', 'html'],
138
+ include: ['src/**/*.ts'], // example, include JS/TS sources to report on
139
+ },
140
+ });
141
+ ```
142
+
143
+ ### vitest 4.x.x Single-Project Config:
144
+ ```typescript
145
+ import { defineConfig } from 'vitest/config';
146
+ import { createAssemblyScriptPool } from 'vitest-pool-assemblyscript/config';
147
+
148
+ export default defineConfig({
149
+ test: {
150
+ pool: createAssemblyScriptPool({
151
+ // no change to available options (stripInline, testMemoryPagesInitial, etc)
152
+ }),
153
+ },
154
+ coverage: {
155
+ // no change to available options
156
+ }
157
+ });
158
+ ```
159
+
160
+ ### vitest 3.2.x Multiple-Project Config:
161
+ ```typescript
162
+ import { defineConfig, defineProject } from 'vitest/config';
163
+ import { defineAssemblyScriptProject } from 'vitest-pool-assemblyscript/config';
164
+
165
+ export default defineConfig({
166
+ test: {
167
+ projects: [
168
+ defineProject({
169
+ test: {
170
+ // JS/TS project config...
171
+ }
172
+ }),
173
+ defineAssemblyScriptProject({
174
+ test: {
175
+ // AS project config... (standard name/label, include, etc)
176
+
177
+ pool: 'vitest-pool-assemblyscript/v3', // in v3, point to the module
178
+ poolOptions: {
179
+ assemblyScript: {
180
+ // same available options as v4 createAssemblyScriptPool are passed here
181
+
182
+ // Additonal - v3 Only
183
+ // maxThreadsV3: 8 // concurrent test file threads to execute (default: availableParallelism - 1)
184
+ }
185
+ }
186
+ }
187
+ })
188
+ ]
189
+ },
190
+
191
+ });
192
+ ```
193
+
194
+ ### vitest 3.2.x Single-Project Config:
195
+ ```typescript
196
+ import { defineAssemblyScriptConfig } from 'vitest-pool-assemblyscript/config';
197
+
198
+ export default defineAssemblyScriptConfig({
199
+ test: {
200
+ pool: 'vitest-pool-assemblyscript/v3',
201
+ poolOptions: {
202
+ assemblyScript: {
203
+ // same available options as v4 createAssemblyScriptPool and v3 multi-project
204
+ }
205
+ }
206
+ },
207
+ });
208
+ ```
209
+
210
+ ### Framework-Provided Imports
211
+
212
+ **`console`**
213
+ The pool provides the full implementation of the [AssemblyScript `console` interface](https://www.assemblyscript.org/stdlib/console.html). This means you can transparently use `console.log("some string")` in your tests, and the output will be fed to vitest and displayed with the test results.
214
+
215
+ If you prefer to do something else with your test console output, you may provide your own versions of these functions to the "env" module - See the next section for details on how to do this.
216
+
217
+ **`trace`**
218
+ The pool also provides an implementation for `trace`, which passes through to Node `console.trace()` immediately for debugging.
219
+
220
+ **`abort`**
221
+ The pool handles assertion errors, runtime errors, and expected throws by providing an abort handler. This cannot be user-overridden.
222
+
223
+
224
+ ### User-Provided Imports with `WasmImportsFactory`
225
+ To provide your own WebAssembly imports, configure `wasmImportsFactory` to point to an ES module which exports a factory function to create your imports:
226
+ ```typescript
227
+ // v4
228
+ // ...
229
+ pool: createAssemblyScriptPool({
230
+ wasmImportsFactory: 'test-helpers/create-imports.js',
231
+ })
232
+ // ...
233
+
234
+ // v3
235
+ // ...
236
+ poolOptions: {
237
+ assemblyScript: {
238
+ wasmImportsFactory: 'test-helpers/create-imports.js',
239
+ }
240
+ }
241
+ // ...
242
+ ```
243
+
244
+ The type signature for this function looks like this:
245
+ ```typescript
246
+ type WasmImportsFactory = (moduleInfo: WasmImportsFactoryInfo) => WebAssembly.Imports;
247
+ ```
248
+
249
+ And the `moduleInfo` argument that it is provided with looks like this:
250
+ ```typescript
251
+ interface WasmImportsFactoryInfo {
252
+ module: WebAssembly.Module;
253
+ memory: WebAssembly.Memory;
254
+ utils: {
255
+ // convenience function for extracting returned strings from WASM memory
256
+ liftString: (stringPtr: number) => string | undefined;
257
+ }
258
+ }
259
+ ```
260
+
261
+ You may provide imports for any module name you wish. Here is an example factory function which uses the "env" module:
262
+ ```js
263
+ export default function createWasmImports({ memory, module, utils }) {
264
+ return {
265
+ env: {
266
+ parseIntStringFunction: (inputStrPtr) => {
267
+ return parseInt(utils.liftString(inputStrPtr));
268
+ }
269
+ }
270
+ };
271
+ }
272
+ ```
273
+
274
+ Example AssemblyScript source code which uses this imported function (the "env" module name is specified):
275
+ ```typescript
276
+ @external("env", "parseIntStringFunction")
277
+ declare function parseIntStringFunction(input: string): i32;
278
+
279
+ export function runParseIntStringFunction(input: string): i32 {
280
+ return parseIntStringFunction(input);
281
+ }
282
+ ```
283
+
284
+ #### Module Names
285
+ If you omit the module name in `@external` (e.g. `@external("parseIntStringFunction")`) or omit `@external` entirely, AssemblyScript uses the source file's own name (without the last file extension) as the module name, making it impractical to provide matching imports to every source file independently if you use imported functions across multiple places in your source. It is recommended to always specify a shared module name (such as "env") for this reason.
286
+
287
+ Conversely, if you need to provide imports targeted to a specific source file, this behavior provides a way to do that as well. For example, if you have a source AS file called `my-file.as.ts` with `declare function myFunc(input: string): i32;` in it and omit the `@external` decorator, then you can import the function *only to this file* with:
288
+ ```js
289
+ export default function createWasmImports({ utils }) {
290
+ return {
291
+ // default source file module name (omits the .ts extension)
292
+ 'my-file.as': {
293
+ myFunc: (inputStrPtr) => {
294
+ return parseInt(utils.liftString(inputStrPtr));
295
+ }
296
+ }
297
+ };
298
+ }
299
+ ```
300
+
301
+ ---
302
+
303
+ ## Writing Tests
304
+
305
+ Import `test`, `describe`, `expect` (and `TestOptions` if needed) from `vitest-pool-assemblyscript/assembly`.
306
+
307
+ `it` is available as an alias for `test`.
308
+
309
+ ```typescript
310
+ import { test, it, describe, expect, TestOptions } from "vitest-pool-assemblyscript/assembly";
311
+ import { add } from "../assembly/math.ts";
312
+
313
+ test("a test", () => {
314
+ expect(1 + 1).toBe(2);
315
+ expect(add(3, 2)).toBe(5);
316
+ });
317
+
318
+ describe("a suite of math operations", () => {
319
+ test("another test", () => {
320
+ expect(3 - 1).toBe(2);
321
+ });
322
+
323
+ describe("a nested suite of float operations", () => {
324
+ it("tests something else", () => {
325
+ expect(0.1 + 0.2).toBeCloseTo(0.3);
326
+ });
327
+ });
328
+ });
329
+ ```
330
+
331
+ ### Modifiers: `.skip`, `.only`, `.fails`
332
+
333
+ ```typescript
334
+ test.skip("not ready yet", () => { /* ... */ });
335
+
336
+ test.only("run only this test", () => { /* ... */ });
337
+
338
+ test.fails("expected to fail, so will actually pass", () => {
339
+ expect(false).toBeTruthy();
340
+ });
341
+
342
+ describe.skip("entire suite skipped", () => { /* ... */ });
343
+
344
+ describe.only("only this suite runs", () => { /* ... */ });
345
+ ```
346
+
347
+ ### Inline Test Options
348
+
349
+ `TestOptions` provides chainable configuration for `timeout`, `retry`, `skip`, `only`, and `fails`. Options can be placed before or after the callback, and suite options are inherited by nested tests and suites.
350
+
351
+ ```typescript
352
+ // options before callback
353
+ test("with timeout", TestOptions.timeout(500), () => { /* ... */ });
354
+
355
+ // options after callback
356
+ test("with retry", () => { /* ... */ }, TestOptions.retry(3));
357
+
358
+ // chained options
359
+ test("with both", TestOptions.timeout(500).retry(2), () => { /* ... */ });
360
+
361
+ // suite-level options are inherited by nested tests
362
+ describe("slow tests", TestOptions.timeout(1000), () => {
363
+ test("inherits suite timeout", () => { /* ... */ });
364
+
365
+ // test-level options override suite options
366
+ test("custom retry", TestOptions.retry(5), () => { /* ... */ });
367
+ });
368
+
369
+ // modifiers and options can be combined
370
+ test.fails("expected failure with retry", TestOptions.retry(3), () => {
371
+ expect(false).toBeTruthy();
372
+ });
373
+ ```
374
+
375
+ ---
376
+
377
+ ## Matcher API
378
+
379
+ This project aims to follow the [vitest/jest `expect()` API](https://vitest.dev/api/expect.html) as closely as possible, with some necessary differences given AssemblyScript's static-typing.
380
+
381
+ The following subset of vitest/jest expect matchers are currently supported:
382
+
383
+ ### `.not`
384
+ Inverts the matcher that follows. Can be chained.
385
+ ```typescript
386
+ expect(1).not.toBe(2);
387
+ expect("hello").not.toBeNull();
388
+ ```
389
+
390
+ ### `toBe()`
391
+ Checks that a value is what you expect. Primitives and strings are compared directly, and references are checked for reference equality only (including objects and arrays). These comparisons are done using `==`, although it is forgiving of numeric type differences.
392
+
393
+ Don't use `toBe` with floating-point numbers - see `toBeCloseTo()` instead.
394
+ ```typescript
395
+ expect(1 + 1).toBe(2);
396
+ expect("hello").toBe("hello");
397
+ ```
398
+
399
+ ### `toBeCloseTo()`
400
+ Checks if a floating point value is close to what you expect. Using exact equality with floating point numbers often doesn't work correctly, because small internal rounding occurs to be able to represent floats in binary. This rounding means intuitive comparisons will often fail.
401
+
402
+ Comparing strings, integers, or references will fall back to using a `toBe` comparison.
403
+
404
+ Accepts an additional `precision: i32` argument - Number of decimal places that must match for values to be considered close. Defaults to 2 digits, meaning effectively that values must be within 0.005 of each other.
405
+ ```typescript
406
+ expect(0.1 + 0.2).toBeCloseTo(0.3);
407
+ expect(1.005).toBeCloseTo(1.0, 1);
408
+ ```
409
+
410
+ ### `toEqual()`
411
+ Checks that two values have the same value (deep equality). Currently supports checking equality of Arrays, Sets, Maps, and nulls. Values inside arrays are compared using `toEqual()` also, while Maps and Sets use their respective rules for membership.
412
+
413
+ Primitives, strings, and other object references are compared with `toBe()` rules.
414
+
415
+ > ⚠️ Warning: Does not yet support user-defined object deep equality checking
416
+ ```typescript
417
+ expect([1, 2, 3]).toEqual([1, 2, 3]);
418
+ expect(["one", "two", "three"]).toEqual(["one", "two", "three"]);
419
+
420
+ // objects use reference equality (deep equality not yet supported)
421
+ const a: MyObject = new MyObject();
422
+ const b: MyObject = new MyObject();
423
+ expect([a, b]).toEqual([a, b]);
424
+ ```
425
+
426
+ ### `toStrictEqual()`
427
+ Alias for `toEqual()`. Currently no differences in AssemblyScript.
428
+
429
+ ### `toBeTruthy()` & `toBeFalsey()`
430
+ Check that a value is truthy or falsey. Falsey values are `0`, `false`, `""`, and `null`.
431
+ ```typescript
432
+ expect(1).toBeTruthy();
433
+ expect(0).toBeFalsey();
434
+ expect("hello").toBeTruthy();
435
+ expect("").toBeFalsey();
436
+ ```
437
+
438
+ ### `toBeNull()`
439
+ Checks that a value is null (`usize(0)` in AssemblyScript).
440
+ ```typescript
441
+ const val: string | null = null;
442
+ expect(val).toBeNull();
443
+ expect("hello").not.toBeNull();
444
+ expect(0).not.toBeNull();
445
+ expect(false).not.toBeNull();
446
+ ```
447
+
448
+ ### `toBeNullable()`
449
+ Checks that the type of the value is nullable (can hold `null`). This is a type-level check, not a value check — use `toBeNull()` to check if a value *is* null.
450
+ ```typescript
451
+ const val: string | null = null;
452
+ expect(val).toBeNullable();
453
+ expect("hello").not.toBeNullable();
454
+ ```
455
+
456
+ ### `toBeNaN()`
457
+ Checks that a floating point value is `NaN`.
458
+ ```typescript
459
+ expect(NaN).toBeNaN();
460
+ expect(1.0).not.toBeNaN();
461
+ ```
462
+
463
+ ### `toHaveLength()`
464
+ Checks that an array or array-like value has the expected length.
465
+ ```typescript
466
+ expect([1, 2, 3]).toHaveLength(3);
467
+ expect([]).toHaveLength(0);
468
+ expect("hello world").toHaveLength(11);
469
+ ```
470
+
471
+ ### `toThrowError()`
472
+ Checks that a function throws an error when called. Optionally checks that the error message matches the provided string. Also available as `toThrow()`.
473
+
474
+ >⚠️ Important: You must provide a void callback to expect() when using `toThrowError()`
475
+
476
+ >ℹ️ Note: `toThrowError()` does not accept inversion using `expect().not.toThrowError()`
477
+ ```typescript
478
+ expect(() => { throw new Error("boom"); }).toThrowError();
479
+ expect(() => { throw new Error("boom"); }).toThrowError("boom");
480
+ ```
481
+
482
+ ### Planned Matchers
483
+ `toBeDefined`, `toBeUndefined`, `toBeGreaterThan`, `toBeGreaterThanOrEqual`, `toBeLessThan`, `toBeLessThanOrEqual`, `toContain`, `toContainEqual`
484
+
485
+ ### Likely Matchers
486
+ `toBeOneOf`, `toBeTypeOf`, `toBeInstanceOf`, `toHaveProperty`, `toMatch`
487
+
488
+ ---
489
+
490
+ ## Project Status & Expectations
491
+
492
+ **This is a pre-v1 project** being developed in the open by an interested individual. Most core functionality is working, with a long list of planned features and polish to be added as time allows.
493
+
494
+ *(Note: Not yet published to npm - currently development only)*
495
+
496
+ ### Current State
497
+
498
+ All features listed in the [Features](#features) section are working and assumed to be bug-free. Please [report a bug](https://github.com/themattspiral/vitest-pool-assemblyscript/issues/new) if you encounter one.
499
+
500
+ **⚠️ Known Limitations - Coming Soon:**
501
+ - **Function-level coverage only**: No statement, branch, or line coverage yet
502
+ - **No lifecycle hooks**: No setup/teardown hooks yet
503
+ - **Watch mode specs only**: Re-runs test files when they are directly changed, but not yet based on changed source files
504
+ - **`toEqual` doesn't reflect**: Doesn't yet support deep inspection of user-defined objects
505
+
506
+ ### Near Future Roadmap
507
+
508
+ **Epic: Enhanced block-level coverage**
509
+ - Block-level statement coverage (line granularity)
510
+ - Branch coverage using CFG analysis
511
+ - All 4 coverage types (function, statement, branch, line)
512
+
513
+ **Epic: Testing DX**
514
+ - Lifecycle hooks (`beforeEach`, `afterEach`, `beforeAll`, `afterAll`)
515
+ - Watch mode optimization
516
+ - `toEqual` reflection
517
+ - expect.soft
518
+ - Allow delegating JS/TS to istanbul coverage provider
519
+ - Per-file compilation setting override?
520
+
521
+ **Epic: Expand expect matcher API**
522
+ - Planned: `toBeDefined`, `toBeUndefined`, `toBeGreaterThan`, `toBeGreaterThanOrEqual`, `toBeLessThan`, `toBeLessThanOrEqual`, `toContain`, `toContainEqual`
523
+ - Probably: `toBeOneOf`, `toBeTypeOf`, `toBeInstanceOf`, `toHaveProperty`, `toMatch`
524
+
525
+ **Epic: Spy and Mock**
526
+ - TBD
527
+
528
+ **✖️ Out of Scope (Currently):**
529
+ - Compiler integration with other compile-to-WASM languages (Rust, C++)
530
+ - I would LOVE to expand this project to a more generic wasm pool, supporting pluggable compilers and ast parsing for different WASM ecosystems and toolchains
531
+ - Not in scope now because of time and effort. If you want to pay me to work on this [get in touch](https://github.com/themattspiral)!
532
+ - Generic JS-harness testing of any precompiled WASM binary
533
+
534
+ ---
535
+
536
+ ## Installation Guide (Development Preview)
537
+
538
+ **⚠️ Important:** This project is under active development. Features and APIs may change without notice. No guarantees are made about stability or functionality.
539
+
540
+ **Feedback Welcome:** If you try this out, please open an issue on GitHub with your experience, bugs, or suggestions!
541
+
542
+ ### Prerequisites
543
+ - Node.js 20.0.0+ (required due to our multi-memory coverage approach)
544
+ - Vitest 3.2.0+ or 4.0.0+
545
+ - AssemblyScript 0.28+
546
+ - C++ build tools (dev only - distributed package will include prebuilds):
547
+ - GCC 7+ or Clang 5+ (C++17 support required)
548
+ - Python 3.x (required by node-gyp)
549
+
550
+ ### Setup
551
+
552
+ 1. **Clone the repository:**
553
+ ```bash
554
+ git clone https://github.com/themattspiral/vitest-pool-assemblyscript.git
555
+ cd vitest-pool-assemblyscript
556
+ ```
557
+
558
+ 2. **Install Binaryen C++ dependencies, then npm deps**
559
+ ```bash
560
+ npm run setup-binaryen
561
+ npm install
562
+ ```
563
+ The `setup-binaryen` script downloads prebuilt Binaryen libraries and C++ headers to `third_party/binaryen/`. These are used to build the native addon that extracts debug info from WASM binaries.
564
+
565
+ 3. **Build Native Addon**
566
+ ```bash
567
+ npm run build:native
568
+ ```
569
+
570
+ 4. **Build Pool**
571
+ ```bash
572
+ npm run build
573
+ ```
574
+
575
+ 5. **Link the pool to your project:**
576
+ ```bash
577
+ # In vitest-pool-assemblyscript:
578
+ npm link
579
+
580
+ # In your project directory:
581
+ npm link vitest-pool-assemblyscript
582
+ ```
583
+
584
+ 6. **Configure Vitest**
585
+
586
+ See the [Configuration](#configuration) section.
587
+
588
+ 7. **Write your tests**
589
+ See the [Writing Tests](#writing-tests) section.
590
+
591
+ 8. **Run your tests:**
592
+ ```bash
593
+ # Run all tests once
594
+ npx vitest run
595
+
596
+ # Run specific test file
597
+ npx vitest run example.as.test.ts
598
+
599
+ # Run specific test in specific file
600
+ npx vitest run example.as.test.ts -t "my test name"
601
+ ```
602
+
603
+ ---
604
+
605
+ ## License
606
+
607
+ [MIT](LICENSE)