()
| 151 | function noop(): void {} |
| 152 | |
| 153 | function getDebugWriter(): BufferedWriter { |
| 154 | if (!debugWriter) { |
| 155 | let ensuredDir: string | null = null |
| 156 | debugWriter = createBufferedWriter({ |
| 157 | writeFn: content => { |
| 158 | const path = getDebugLogPath() |
| 159 | const dir = dirname(path) |
| 160 | const needMkdir = ensuredDir !== dir |
| 161 | ensuredDir = dir |
| 162 | if (isDebugMode()) { |
| 163 | // immediateMode: must stay sync. Async writes are lost on direct |
| 164 | // process.exit() and keep the event loop alive in beforeExit |
| 165 | // handlers (infinite loop with Perfetto tracing). See #22257. |
| 166 | if (needMkdir) { |
| 167 | try { |
| 168 | getFsImplementation().mkdirSync(dir) |
| 169 | } catch { |
| 170 | // Directory already exists |
| 171 | } |
| 172 | } |
| 173 | getFsImplementation().appendFileSync(path, content) |
| 174 | void updateLatestDebugLogSymlink() |
| 175 | return |
| 176 | } |
| 177 | // Buffered path (ants without --debug): flushes ~1/sec so chain |
| 178 | // depth stays ~1. .bind over a closure so only the bound args are |
| 179 | // retained, not this scope. |
| 180 | pendingWrite = pendingWrite |
| 181 | .then(appendAsync.bind(null, needMkdir, dir, path, content)) |
| 182 | .catch(noop) |
| 183 | }, |
| 184 | flushIntervalMs: 1000, |
| 185 | maxBufferSize: 100, |
| 186 | immediateMode: isDebugMode(), |
| 187 | }) |
| 188 | registerCleanup(async () => { |
| 189 | debugWriter?.dispose() |
| 190 | await pendingWrite |
| 191 | }) |
| 192 | } |
| 193 | return debugWriter |
| 194 | } |
| 195 | |
| 196 | export async function flushDebugLogs(): Promise<void> { |
| 197 | debugWriter?.flush() |
no test coverage detected