The koffi IFileOpenDialog conversation runs in a spawned child process instead of a worker thread: the dialog is the child's first window, so Windows activates it without a foreground call, and a native fault stays contained to the child. The driver maps the child's message protocol onto a promise and services aborts by posting WM_CLOSE to the dialog thread's windows, killing the child when the close budget is exhausted. The built worker ships as lib/worker.cjs (the ./worker export) under plain node, and win32-dialog.spec.ts returns to the thread-safe pool.
34 lines
1.7 KiB
TypeScript
34 lines
1.7 KiB
TypeScript
/**
|
|
* Real-process half of the Win32 dialog driver: spawn the dialog child
|
|
* process (source or built plane) and close a dialog thread's windows. The
|
|
* module itself loads everywhere (the import chain from native-picker.ts is
|
|
* static); what stays win32-only is koffi, imported dynamically inside the
|
|
* bindings' functions. The driver's logic is tested against fakes of this
|
|
* surface instead.
|
|
*/
|
|
|
|
import { spawn, type StdioOptions } from 'node:child_process'
|
|
import { fileURLToPath } from 'node:url'
|
|
import type { Win32DialogWorkerData } from './win32-dialog-worker.ts'
|
|
|
|
/**
|
|
* Spawn the dialog child process. Built consumers launch the bundled CJS
|
|
* entry next to this module under plain node; unbuilt (source) consumers
|
|
* bootstrap tsx first, mirroring the dsh CLI's source launch. The dialog is
|
|
* the child's first window, so Windows activates it without a foreground
|
|
* call.
|
|
* @param data - the child payload (dialog title).
|
|
* @returns the spawned child process.
|
|
*/
|
|
export function spawnDialogWorker(data: Win32DialogWorkerData): ReturnType<typeof spawn> {
|
|
const env = { ...process.env, DSH_DIALOG_TITLE: data.title }
|
|
const stdio: StdioOptions = ['ignore', 'inherit', 'inherit', 'ipc']
|
|
/* v8 ignore next 3 -- the built-output arm: tests always run unbuilt (src/) */
|
|
if (!import.meta.url.endsWith('.ts')) {
|
|
return spawn(process.execPath, [fileURLToPath(new URL('./worker.cjs', import.meta.url))], { env, stdio, windowsHide: true })
|
|
}
|
|
return spawn(process.execPath, ['--import', import.meta.resolve('tsx/esm'), fileURLToPath(new URL('./win32-dialog-worker.ts', import.meta.url))], { env, stdio, windowsHide: true })
|
|
}
|
|
|
|
export { closeThreadWindows } from './win32-dialog-bindings.ts'
|