fix(picker): pointer-width vtable offsets, COM apartment pairing, unconditional abort budget, and the full failure chain

Review round two on the in-process dialog:

- Vtable slots and out-pointers use koffi.sizeof('void *') instead of a
  hardcoded 8 - win32-ia32 (which Node and koffi both ship) would have read
  method pointers from the wrong address and crashed in-process before any
  fallback could run.
- runFolderDialog pairs every successful (incl. S_FALSE) CoInitializeEx
  with CoUninitialize in the outermost finally, releasing the dialog first;
  a failed init is deliberately unpaired. Pinned across fake-bindings and
  mocked-koffi suites.
- The abort close budget starts unconditionally: a worker hung before the
  showing notice (koffi import or COM init) now ends in terminate instead
  of a dangling promise; WM_CLOSE posting still waits for the thread id.
- A triple miss (dialog + pwsh + 5.1) surfaces an AggregateError carrying
  all three causes - the in-process tier's reason was previously
  unrecoverable from the final PowerShell error.
- The stray '=>{ ' formatter artifacts are normalized to real blocks.

Both stale note claims from the review are fixed: the DPI note's
Consequences no longer claims an ENOENT classification or zero new
dependencies, and the 2026-07-27 picker note's Windows bullet now names
the in-process primary and keeps the PowerShell chain as fallback (both
languages, pairings re-recorded).
This commit is contained in:
Huanqi Cao
2026-08-03 20:40:10 +08:00
parent fed3149ac4
commit 8500a21658
15 changed files with 147 additions and 50 deletions
@@ -31,6 +31,7 @@ interface ComWorld {
posted: { hwnd: unknown; message: number }[]
registered: number
unregistered: number
uninitialized: number
}
function comWorld(overrides: Partial<ComWorld> = {}): ComWorld {
@@ -39,7 +40,7 @@ function comWorld(overrides: Partial<ComWorld> = {}): ComWorld {
hasThreadDpi: true, enumThrows: false,
path: 'C:\\选中\\directory',
titles: [], options: [], dpiContexts: [], freed: [], released: [], posted: [],
registered: 0, unregistered: 0,
registered: 0, unregistered: 0, uninitialized: 0,
...overrides,
}
}
@@ -85,6 +86,7 @@ function installFakeKoffi(world: ComWorld): void {
func: (_convention: string, name: string, _result: string, _args: string[]) => {
switch (name) {
case 'CoInitializeEx': return () => world.coInitHr
case 'CoUninitialize': return () => { world.uninitialized += 1 }
case 'CoCreateInstance': return (...args: unknown[]) => {
if (world.coCreateHr < 0) return world.coCreateHr
outBuffers.set(args[4], dialogPtr)
@@ -109,6 +111,7 @@ function installFakeKoffi(world: ComWorld): void {
}),
proto: (declaration: string) => ({ declaration }),
pointer: (type: unknown) => type,
sizeof: (type: string) => { void type; return 8 },
register: (fn: (hwnd: unknown, lparam: unknown) => number) => { world.registered += 1; return { fn } },
unregister: () => { world.unregistered += 1 },
decode: (value: unknown, offsetOrType: unknown): unknown => {
@@ -153,6 +156,7 @@ describe('loadWin32DialogBindings over the fake COM world', () => {
expect(showing).toHaveBeenCalledWith(31337)
expect(world.freed).toHaveLength(1)
expect(world.released).toEqual(['item', 'dialog'])
expect(world.uninitialized).toBe(1)
})
it('maps dismissal, missing DPI support, and the S_FALSE CoInitializeEx', async () => {
@@ -163,6 +167,7 @@ describe('loadWin32DialogBindings over the fake COM world', () => {
expect(runFolderDialog(bindings, 'Pick', vi.fn())).toBeNull()
expect(world.dpiContexts).toEqual([])
expect(world.released).toEqual(['dialog'])
expect(world.uninitialized).toBe(1)
})
it('surfaces creation and extraction failures as HRESULT errors', async () => {
@@ -225,6 +230,7 @@ describe('the worker entry over a mocked thread boundary', () => {
loadWin32DialogBindings: async () => ({
setThreadDpiAwareness: () => undefined,
coInitializeSta: () => 0,
coUninitialize: () => undefined,
currentThreadId: () => 11,
createFolderDialog: () => ({
setOptions: () => 0,