| 16 | const busy = (error: unknown) => |
| 17 | typeof error === "object" && error !== null && "code" in error && error.code === "EBUSY" |
| 18 | const rm = async (left: number): Promise<void> => { |
| 19 | Bun.gc(true) |
| 20 | await sleep(100) |
| 21 | return fs.rm(dir, { recursive: true, force: true }).catch((error) => { |
| 22 | if (!busy(error)) throw error |
| 23 | if (left <= 1 && process.platform !== "win32") throw error |
| 24 | if (left <= 1) return |
| 25 | return rm(left - 1) |
| 26 | }) |
| 27 | } |
| 28 | |
| 29 | // Windows can keep SQLite WAL handles alive until GC finalizers run, so we |
| 30 | // force GC and retry teardown to avoid flaky EBUSY in test cleanup. |